Index: boot/Makefile.common
===================================================================
--- boot/Makefile.common	(revision d11a1811118ec8e5eb8ca4beae291275a4ce36b6)
+++ boot/Makefile.common	(revision 85f20643f5a50d25ca775e64fad72573fcdf8e7d)
@@ -187,5 +187,6 @@
 	$(USPACE_PATH)/app/vuhid/vuh \
 	$(USPACE_PATH)/app/mkbd/mkbd \
-	$(USPACE_PATH)/app/websrv/websrv
+	$(USPACE_PATH)/app/websrv/websrv \
+	$(USPACE_PATH)/app/date/date
 
 ifeq ($(CONFIG_PCC),y)
Index: boot/arch/amd64/Makefile.inc
===================================================================
--- boot/arch/amd64/Makefile.inc	(revision d11a1811118ec8e5eb8ca4beae291275a4ce36b6)
+++ boot/arch/amd64/Makefile.inc	(revision 85f20643f5a50d25ca775e64fad72573fcdf8e7d)
@@ -42,4 +42,5 @@
 	char/ps2mouse \
 	char/xtkbd \
+	time/cmos-rtc \
 	bus/usb/ehci\
 	bus/usb/ohci \
Index: uspace/Makefile
===================================================================
--- uspace/Makefile	(revision d11a1811118ec8e5eb8ca4beae291275a4ce36b6)
+++ uspace/Makefile	(revision 85f20643f5a50d25ca775e64fad72573fcdf8e7d)
@@ -70,4 +70,5 @@
 	app/sysinfo \
 	app/mkbd \
+	app/date \
 	srv/clip \
 	srv/loc \
@@ -125,5 +126,5 @@
 	drv/nic/ne2k \
 	drv/nic/e1k \
-	drv/nic/rtl8139
+	drv/nic/rtl8139 \
 
 ifeq ($(CONFIG_PCC),y)
@@ -149,4 +150,5 @@
 		drv/bus/isa \
 		drv/char/ns8250 \
+		drv/time/cmos-rtc \
 		srv/hw/irc/apic \
 		srv/hw/irc/i8259
@@ -159,4 +161,5 @@
 		drv/bus/isa \
 		drv/char/ns8250 \
+		drv/time/cmos-rtc \
 		srv/hw/irc/apic \
 		srv/hw/irc/i8259
Index: uspace/app/date/Makefile
===================================================================
--- uspace/app/date/Makefile	(revision 85f20643f5a50d25ca775e64fad72573fcdf8e7d)
+++ uspace/app/date/Makefile	(revision 85f20643f5a50d25ca775e64fad72573fcdf8e7d)
@@ -0,0 +1,35 @@
+#
+# Copyright (c) 2012 Maurizio Lombardi
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# - Redistributions of source code must retain the above copyright
+#   notice, this list of conditions and the following disclaimer.
+# - Redistributions in binary form must reproduce the above copyright
+#   notice, this list of conditions and the following disclaimer in the
+#   documentation and/or other materials provided with the distribution.
+# - The name of the author may not be used to endorse or promote products
+#   derived from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+
+USPACE_PREFIX = ../..
+BINARY = date
+
+SOURCES = \
+	date.c
+
+include $(USPACE_PREFIX)/Makefile.common
Index: uspace/app/date/date.c
===================================================================
--- uspace/app/date/date.c	(revision 85f20643f5a50d25ca775e64fad72573fcdf8e7d)
+++ uspace/app/date/date.c	(revision 85f20643f5a50d25ca775e64fad72573fcdf8e7d)
@@ -0,0 +1,120 @@
+/*
+ * Copyright (c) 2012 Maurizio Lombardi
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+#include <stdio.h>
+#include <device/clock_dev.h>
+#include <errno.h>
+#include <loc.h>
+#include <time.h>
+#include <malloc.h>
+#include <ipc/clock_ctl.h>
+
+#define NAME   "date"
+
+int
+main(int argc, char **argv)
+{
+	int rc;
+	category_id_t cat_id;
+	size_t svc_cnt;
+	service_id_t  *svc_ids = NULL;
+	service_id_t svc_id;
+	char *svc_name = NULL;
+
+	sysarg_t battery_ok;
+	struct tm t;
+
+	/* Get the id of the clock category */
+	rc = loc_category_get_id("clock", &cat_id, IPC_FLAG_BLOCKING);
+	if (rc != EOK) {
+		printf(NAME ": Cannot get clock category id\n");
+		goto exit;
+	}
+
+	/* Get the list of available services in the clock category */
+	rc = loc_category_get_svcs(cat_id, &svc_ids, &svc_cnt);
+	if (rc != EOK) {
+		printf(NAME ": Cannot get the list of services in category \
+		    clock\n");
+		goto exit;
+	}
+
+	/* Check if the are available services in the clock category */
+	if (svc_cnt == 0) {
+		printf(NAME ": No available service found in \
+		    the clock category\n");
+		goto exit;
+	}
+
+	/* Get the name of the clock service */
+	rc = loc_service_get_name(svc_ids[0], &svc_name);
+	if (rc != EOK) {
+		printf(NAME ": Cannot get the name of the service\n");
+		goto exit;
+	}
+
+	/* Get the service id for the device */
+	rc = loc_service_get_id(svc_name, &svc_id, 0);
+	if (rc != EOK) {
+		printf(NAME ": Cannot get the service id for device %s",
+		    svc_name);
+		goto exit;
+	}
+
+	/* Connect to the device */
+	async_sess_t *sess = loc_service_connect(EXCHANGE_SERIALIZE,
+	    svc_id, 0);
+	if (!sess) {
+		printf(NAME ": Cannot connect to the device\n");
+		goto exit;
+	}
+
+	async_exch_t *exch = async_exchange_begin(sess);
+	rc = async_req_0_1(exch, CLOCK_GET_BATTERY_STATUS, &battery_ok);
+	async_exchange_end(exch);
+
+	if (rc == EOK && !battery_ok)
+		printf(NAME ": Warning! RTC battery dead\n");
+
+	/* Read the current date/time */
+	rc = clock_dev_time_get(sess, &t);
+	if (rc != EOK) {
+		printf(NAME ": Cannot read the current time\n");
+		goto exit;
+	}
+
+	printf("%02d/%02d/%d ", t.tm_mday, t.tm_mon + 1, 1900 + t.tm_year);
+	printf("%02d:%02d:%02d\n", t.tm_hour, t.tm_min, t.tm_sec);
+
+exit:
+	free(svc_name);
+	free(svc_ids);
+	return rc;
+}
+
Index: uspace/drv/bus/isa/isa.dev
===================================================================
--- uspace/drv/bus/isa/isa.dev	(revision d11a1811118ec8e5eb8ca4beae291275a4ce36b6)
+++ uspace/drv/bus/isa/isa.dev	(revision 85f20643f5a50d25ca775e64fad72573fcdf8e7d)
@@ -27,2 +27,6 @@
 	dma 1
 	dma 5
+
+cmos-rtc:
+	match 100 isa/cmos-rtc
+	io_range 70 2
Index: uspace/drv/time/cmos-rtc/Makefile
===================================================================
--- uspace/drv/time/cmos-rtc/Makefile	(revision 85f20643f5a50d25ca775e64fad72573fcdf8e7d)
+++ uspace/drv/time/cmos-rtc/Makefile	(revision 85f20643f5a50d25ca775e64fad72573fcdf8e7d)
@@ -0,0 +1,37 @@
+#
+# Copyright (c) 2012 Maurizio Lombardi
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# - Redistributions of source code must retain the above copyright
+#   notice, this list of conditions and the following disclaimer.
+# - Redistributions in binary form must reproduce the above copyright
+#   notice, this list of conditions and the following disclaimer in the
+#   documentation and/or other materials provided with the distribution.
+# - The name of the author may not be used to endorse or promote products
+#   derived from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+
+USPACE_PREFIX = ../../..
+LIBS = $(LIBDRV_PREFIX)/libdrv.a
+EXTRA_CFLAGS += -I$(LIBDRV_PREFIX)/include
+BINARY = cmos-rtc
+
+SOURCES = \
+	cmos-rtc.c
+
+include $(USPACE_PREFIX)/Makefile.common
Index: uspace/drv/time/cmos-rtc/cmos-regs.h
===================================================================
--- uspace/drv/time/cmos-rtc/cmos-regs.h	(revision 85f20643f5a50d25ca775e64fad72573fcdf8e7d)
+++ uspace/drv/time/cmos-rtc/cmos-regs.h	(revision 85f20643f5a50d25ca775e64fad72573fcdf8e7d)
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2012 Maurizio Lombardi
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef _CMOS_RTC_H_
+#define _CMOS_RTC_H_
+
+#define RTC_SEC         0x00
+#define RTC_MIN         0x02
+#define RTC_HOUR        0x04
+#define RTC_DAY         0x07
+#define RTC_MON         0x08
+#define RTC_YEAR        0x09
+
+#define RTC_STATUS_B    0x0B
+#define RTC_MASK_BCD    0x04
+
+#define RTC_STATUS_D    0x0D
+#define RTC_BATTERY_OK  0x80
+
+#define RTC_UPDATE      0x0A
+#define RTC_MASK_UPDATE 0x08
+
+#endif
+
Index: uspace/drv/time/cmos-rtc/cmos-rtc.c
===================================================================
--- uspace/drv/time/cmos-rtc/cmos-rtc.c	(revision 85f20643f5a50d25ca775e64fad72573fcdf8e7d)
+++ uspace/drv/time/cmos-rtc/cmos-rtc.c	(revision 85f20643f5a50d25ca775e64fad72573fcdf8e7d)
@@ -0,0 +1,481 @@
+/*
+ * Copyright (c) 2012 Maurizio Lombardi
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/**
+ * @defgroup CMOS RTC driver.
+ * @brief HelenOS RTC driver.
+ * @{
+ */
+
+/** @file
+ */
+
+#include <errno.h>
+#include <ddi.h>
+#include <libarch/ddi.h>
+#include <stdio.h>
+#include <ddf/driver.h>
+#include <ddf/log.h>
+#include <ops/clock_dev.h>
+#include <fibril_synch.h>
+#include <device/hw_res.h>
+#include <devman.h>
+#include <ipc/clock_ctl.h>
+
+#include "cmos-regs.h"
+
+#define NAME "cmos-rtc"
+
+#define REG_COUNT 2
+
+#define RTC_FROM_FNODE(fnode)  ((rtc_t *) ((fnode)->dev->driver_data))
+
+typedef struct rtc {
+	/** DDF device node */
+	ddf_dev_t *dev;
+	/** DDF function node */
+	ddf_fun_t *fun;
+	/** The fibril mutex for synchronizing the access to the device */
+	fibril_mutex_t mutex;
+	/** The base I/O address of the device registers */
+	uint32_t io_addr;
+	/** The I/O port used to access the CMOS registers */
+	ioport8_t *port;
+	/** true if a client is connected to the device */
+	bool client_connected;
+} rtc_t;
+
+
+static int  rtc_time_get(ddf_fun_t *fun, struct tm *t);
+static int  rtc_time_set(ddf_fun_t *fun, struct tm *t);
+static int  rtc_dev_add(ddf_dev_t *dev);
+static int  rtc_dev_initialize(rtc_t *rtc);
+static bool rtc_pio_enable(rtc_t *rtc);
+static void rtc_dev_cleanup(rtc_t *rtc);
+static int  rtc_open(ddf_fun_t *fun);
+static void rtc_close(ddf_fun_t *fun);
+static bool rtc_update_in_progress(rtc_t *rtc);
+static int  rtc_register_read(rtc_t *rtc, int reg);
+static int  bcd2dec(int bcd);
+static void rtc_default_handler(ddf_fun_t *fun,
+    ipc_callid_t callid, ipc_call_t *call);
+
+
+static ddf_dev_ops_t rtc_dev_ops;
+
+/** The RTC device driver's standard operations */
+static driver_ops_t rtc_ops = {
+	.dev_add = rtc_dev_add,
+	.dev_remove = NULL, /* XXX */
+};
+
+/** The RTC device driver structure */
+static driver_t rtc_driver = {
+	.name = NAME,
+	.driver_ops = &rtc_ops,
+};
+
+/** Clock interface */
+static clock_dev_ops_t rtc_clock_dev_ops = {
+	.time_get = rtc_time_get,
+	.time_set = rtc_time_set,
+};
+
+/** Initialize the RTC driver */
+static void
+rtc_init(void)
+{
+	ddf_log_init(NAME, LVL_ERROR);
+
+	rtc_dev_ops.open = rtc_open;
+	rtc_dev_ops.close = rtc_close;
+
+	rtc_dev_ops.interfaces[CLOCK_DEV_IFACE] = &rtc_clock_dev_ops;
+	rtc_dev_ops.default_handler = &rtc_default_handler;
+}
+
+/** Clean up the RTC soft state
+ *
+ * @param rtc  The RTC device
+ */
+static void
+rtc_dev_cleanup(rtc_t *rtc)
+{
+	if (rtc->dev->parent_sess) {
+		async_hangup(rtc->dev->parent_sess);
+		rtc->dev->parent_sess = NULL;
+	}
+}
+
+/** Enable the I/O ports of the device
+ *
+ * @param rtc  The real time clock device
+ *
+ * @return  true in case of success, false otherwise
+ */
+static bool
+rtc_pio_enable(rtc_t *rtc)
+{
+	if (pio_enable((void *)(uintptr_t) rtc->io_addr, REG_COUNT,
+	    (void **) &rtc->port)) {
+
+		ddf_msg(LVL_ERROR, "Cannot map the port %#" PRIx32
+		    " for device %s", rtc->io_addr, rtc->dev->name);
+		return false;
+	}
+
+	return true;
+}
+
+/** Initialize the RTC device
+ *
+ * @param rtc  Pointer to the RTC device
+ *
+ * @return  EOK on success or a negative error code
+ */ 
+static int
+rtc_dev_initialize(rtc_t *rtc)
+{
+	int rc;
+	size_t i;
+	hw_resource_t *res;
+	bool ioport = false;
+
+	ddf_msg(LVL_DEBUG, "rtc_dev_initialize %s", rtc->dev->name);
+
+	hw_resource_list_t hw_resources;
+	memset(&hw_resources, 0, sizeof(hw_resource_list_t));
+
+	/* Connect to the parent's driver */
+
+	rtc->dev->parent_sess = devman_parent_device_connect(EXCHANGE_SERIALIZE,
+	    rtc->dev->handle, IPC_FLAG_BLOCKING);
+	if (!rtc->dev->parent_sess) {
+		ddf_msg(LVL_ERROR, "Failed to connect to parent driver\
+		    of device %s.", rtc->dev->name);
+		rc = ENOENT;
+		goto error;
+	}
+
+	/* Get the HW resources */
+	rc = hw_res_get_resource_list(rtc->dev->parent_sess, &hw_resources);
+	if (rc != EOK) {
+		ddf_msg(LVL_ERROR, "Failed to get HW resources\
+		    for device %s", rtc->dev->name);
+		goto error;
+	}
+
+	for (i = 0; i < hw_resources.count; ++i) {
+		res = &hw_resources.resources[i];
+
+		if (res->type == IO_RANGE) {
+			if (res->res.io_range.size < REG_COUNT) {
+				ddf_msg(LVL_ERROR, "I/O range assigned to \
+				    device %s is too small", rtc->dev->name);
+				rc = ELIMIT;
+				goto error;
+			}
+			rtc->io_addr = res->res.io_range.address;
+			ioport = true;
+			ddf_msg(LVL_NOTE, "Device %s was assigned I/O address \
+			    0x%x", rtc->dev->name, rtc->io_addr);
+		}
+	}
+
+	if (!ioport) {
+		/* No I/O address assigned to this device */
+		ddf_msg(LVL_ERROR, "Missing HW resource for device %s",
+		    rtc->dev->name);
+		rc = ENOENT;
+		goto error;
+	}
+
+	hw_res_clean_resource_list(&hw_resources);
+
+	return EOK;
+
+error:
+	rtc_dev_cleanup(rtc);
+	hw_res_clean_resource_list(&hw_resources);
+
+	return rc;
+}
+
+/** Read a register from the CMOS memory
+ *
+ * @param port   The I/O port assigned to the device
+ * @param reg    The index of the register to read
+ *
+ * @return       The value of the register
+ */
+static int
+rtc_register_read(rtc_t *rtc, int reg)
+{
+	pio_write_8(rtc->port, reg);
+	return pio_read_8(rtc->port + 1);
+}
+
+/** Check if an update is in progress
+ *
+ * @param rtc  The rtc device
+ *
+ * @return  true if an update is in progress, false otherwise
+ */
+static bool
+rtc_update_in_progress(rtc_t *rtc)
+{
+	return rtc_register_read(rtc, RTC_UPDATE) & RTC_MASK_UPDATE;
+}
+
+/** Read the current time from the CMOS
+ *
+ * @param fun  The RTC function
+ * @param t    Pointer to the time variable
+ *
+ * @return  EOK on success or a negative error code
+ */
+static int
+rtc_time_get(ddf_fun_t *fun, struct tm *t)
+{
+	bool bcd_mode;
+	rtc_t *rtc = RTC_FROM_FNODE(fun);
+
+	fibril_mutex_lock(&rtc->mutex);
+
+	/* now read the registers */
+	do {
+		/* Suspend until the update process has finished */
+		while (rtc_update_in_progress(rtc));
+
+		t->tm_sec  = rtc_register_read(rtc, RTC_SEC);
+		t->tm_min  = rtc_register_read(rtc, RTC_MIN);
+		t->tm_hour = rtc_register_read(rtc, RTC_HOUR);
+		t->tm_mday = rtc_register_read(rtc, RTC_DAY);
+		t->tm_mon  = rtc_register_read(rtc, RTC_MON);
+		t->tm_year = rtc_register_read(rtc, RTC_YEAR);
+
+		/* Now check if it is stable */
+	} while( t->tm_sec  != rtc_register_read(rtc, RTC_SEC) ||
+		 t->tm_min  != rtc_register_read(rtc, RTC_MIN) ||
+		 t->tm_mday != rtc_register_read(rtc, RTC_DAY) ||
+		 t->tm_mon  != rtc_register_read(rtc, RTC_MON) ||
+		 t->tm_year != rtc_register_read(rtc, RTC_YEAR));
+
+	/* Check if the RTC is working in BCD mode */
+	bcd_mode = !(rtc_register_read(rtc, RTC_STATUS_B) & RTC_MASK_BCD);
+
+	if (bcd_mode) {
+		t->tm_sec  = bcd2dec(t->tm_sec);
+		t->tm_min  = bcd2dec(t->tm_min);
+		t->tm_hour = bcd2dec(t->tm_hour);
+		t->tm_mday = bcd2dec(t->tm_mday);
+		t->tm_mon  = bcd2dec(t->tm_mon);
+		t->tm_year = bcd2dec(t->tm_year);
+	}
+
+	/* Count the months starting from 0, not from 1 */
+	t->tm_mon--;
+
+	if (t->tm_year < 100) {
+		/* tm_year is the number of years since 1900, it is not
+		 * possible it is < 100.
+		 */
+		t->tm_year += 100;
+	}
+
+	fibril_mutex_unlock(&rtc->mutex);
+	return EOK;
+}
+
+/** Set the time in the RTC
+ *
+ * @param fun  The RTC function
+ * @param t    The time value to set
+ *
+ * @return  EOK or a negative error code
+ */
+static int
+rtc_time_set(ddf_fun_t *fun, struct tm *t)
+{
+	return EOK;
+}
+
+/** The dev_add callback of the rtc driver
+ *
+ * @param dev  The RTC device
+ *
+ * @return  EOK on success or a negative error code
+ */
+static int
+rtc_dev_add(ddf_dev_t *dev)
+{
+	rtc_t *rtc;
+	ddf_fun_t *fun = NULL;
+	int rc;
+	bool need_cleanup = false;
+
+	ddf_msg(LVL_DEBUG, "rtc_dev_add %s (handle = %d)",
+	    dev->name, (int) dev->handle);
+
+	rtc = ddf_dev_data_alloc(dev, sizeof(rtc_t));
+	if (!rtc)
+		return ENOMEM;
+
+	rtc->dev = dev;
+	fibril_mutex_initialize(&rtc->mutex);
+
+	rc = rtc_dev_initialize(rtc);
+	if (rc != EOK)
+		goto error;
+
+	need_cleanup = true;
+
+	if (!rtc_pio_enable(rtc)) {
+		rc = EADDRNOTAVAIL;
+		goto error;
+	}
+
+	fun = ddf_fun_create(dev, fun_exposed, "a");
+	if (!fun) {
+		ddf_msg(LVL_ERROR, "Failed creating function");
+		rc = ENOENT;
+		goto error;
+	}
+
+	fun->ops = &rtc_dev_ops;
+	rc = ddf_fun_bind(fun);
+	if (rc != EOK) {
+		ddf_msg(LVL_ERROR, "Failed binding function");
+		goto error;
+	}
+
+	rtc->fun = fun;
+
+	ddf_fun_add_to_category(fun, "clock");
+
+	rtc->client_connected = false;
+
+	ddf_msg(LVL_NOTE, "Device %s successfully initialized",
+	    dev->name);
+
+	return rc;
+
+error:
+	if (fun)
+		ddf_fun_destroy(fun);
+	if (need_cleanup)
+		rtc_dev_cleanup(rtc);
+	return rc;
+}
+
+/** Default handler for client requests not handled
+ *  by the standard interface
+ */
+static void
+rtc_default_handler(ddf_fun_t *fun, ipc_callid_t callid, ipc_call_t *call)
+{
+	sysarg_t method = IPC_GET_IMETHOD(*call);
+	rtc_t *rtc = RTC_FROM_FNODE(fun);
+	bool batt_ok;
+
+	switch (method) {
+	case CLOCK_GET_BATTERY_STATUS:
+		batt_ok = rtc_register_read(rtc, RTC_STATUS_D) &
+		    RTC_BATTERY_OK;
+		async_answer_1(callid, EOK, batt_ok);
+		break;
+	default:
+		async_answer_0(callid, ENOTSUP);
+	}
+}
+
+/** Open the device
+ *
+ * @param fun   The function node
+ *
+ * @return  EOK on success or a negative error code
+ */
+static int
+rtc_open(ddf_fun_t *fun)
+{
+	int rc;
+	rtc_t *rtc = RTC_FROM_FNODE(fun);
+
+	fibril_mutex_lock(&rtc->mutex);
+
+	if (rtc->client_connected)
+		rc = EBUSY;
+	else {
+		rc = EOK;
+		rtc->client_connected = true;
+	}
+
+	fibril_mutex_unlock(&rtc->mutex);
+	return rc;
+}
+
+/** Close the device
+ *
+ * @param fun  The function node
+ */
+static void
+rtc_close(ddf_fun_t *fun)
+{
+	rtc_t *rtc = RTC_FROM_FNODE(fun);
+
+	fibril_mutex_lock(&rtc->mutex);
+
+	assert(rtc->client_connected);
+	rtc->client_connected = false;
+
+	fibril_mutex_unlock(&rtc->mutex);
+}
+
+/** Convert from BCD mode to binary mode
+ *
+ * @param bcd   The number in BCD format to convert
+ *
+ * @return      The converted value
+ */
+static int
+bcd2dec(int bcd)
+{
+	return ((bcd & 0xF0) >> 1) + ((bcd & 0xF0) >> 3) + (bcd & 0xf);
+}
+
+int
+main(int argc, char **argv)
+{
+	printf(NAME ": HelenOS RTC driver\n");
+	rtc_init();
+	return ddf_driver_main(&rtc_driver);
+}
+
+/**
+ * @}
+ */
Index: uspace/drv/time/cmos-rtc/cmos-rtc.ma
===================================================================
--- uspace/drv/time/cmos-rtc/cmos-rtc.ma	(revision 85f20643f5a50d25ca775e64fad72573fcdf8e7d)
+++ uspace/drv/time/cmos-rtc/cmos-rtc.ma	(revision 85f20643f5a50d25ca775e64fad72573fcdf8e7d)
@@ -0,0 +1,1 @@
+100 isa/cmos-rtc
Index: uspace/lib/c/Makefile
===================================================================
--- uspace/lib/c/Makefile	(revision d11a1811118ec8e5eb8ca4beae291275a4ce36b6)
+++ uspace/lib/c/Makefile	(revision 85f20643f5a50d25ca775e64fad72573fcdf8e7d)
@@ -69,4 +69,5 @@
 	generic/device/hw_res_parsed.c \
 	generic/device/char_dev.c \
+	generic/device/clock_dev.c \
 	generic/device/nic.c \
 	generic/device/pci.c \
Index: uspace/lib/c/generic/device/clock_dev.c
===================================================================
--- uspace/lib/c/generic/device/clock_dev.c	(revision 85f20643f5a50d25ca775e64fad72573fcdf8e7d)
+++ uspace/lib/c/generic/device/clock_dev.c	(revision 85f20643f5a50d25ca775e64fad72573fcdf8e7d)
@@ -0,0 +1,79 @@
+/*
+ * Copyright (c) 2012 Maurizio Lombardi
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+ /** @addtogroup libc
+ * @{
+ */
+/** @file
+ */
+
+#include <ipc/dev_iface.h>
+#include <device/clock_dev.h>
+#include <errno.h>
+#include <async.h>
+#include <time.h>
+
+/** Read the current time from the device
+ *
+ * @param sess     Session of the device
+ * @param t        The current time that will be read from the device
+ *
+ * @return         EOK on success or a negative error code
+ */
+int
+clock_dev_time_get(async_sess_t *sess, struct tm *t)
+{
+	ipc_call_t answer;
+	aid_t req;
+	int ret;
+
+	async_exch_t *exch = async_exchange_begin(sess);
+
+	req = async_send_1(exch, DEV_IFACE_ID(CLOCK_DEV_IFACE),
+	    CLOCK_DEV_TIME_GET, &answer);
+	ret = async_data_read_start(exch, t, sizeof(*t));
+
+	async_exchange_end(exch);
+
+	sysarg_t rc;
+	if (ret != EOK) {
+		async_wait_for(req, &rc);
+		if (rc == EOK)
+			return ret;
+	}
+
+	async_wait_for(req, &rc);
+	if ((int) rc != EOK)
+		return ret;
+
+	return (int) IPC_GET_ARG1(answer);
+}
+
+/** @}
+ */
+
Index: uspace/lib/c/include/device/clock_dev.h
===================================================================
--- uspace/lib/c/include/device/clock_dev.h	(revision 85f20643f5a50d25ca775e64fad72573fcdf8e7d)
+++ uspace/lib/c/include/device/clock_dev.h	(revision 85f20643f5a50d25ca775e64fad72573fcdf8e7d)
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2012 Maurizio Lombardi
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup libc
+ * @{
+ */
+/** @file
+ */
+
+#ifndef LIBC_DEVICE_CLOCK_DEV_H_
+#define LIBC_DEVICE_CLOCK_DEV_H_
+
+#include <async.h>
+#include <time.h>
+
+typedef enum {
+	CLOCK_DEV_TIME_GET = 0,
+	CLOCK_DEV_TIME_SET,
+} clock_dev_method_t;
+
+extern int clock_dev_time_get(async_sess_t *, struct tm *);
+
+#endif
+
Index: uspace/lib/c/include/ipc/clock_ctl.h
===================================================================
--- uspace/lib/c/include/ipc/clock_ctl.h	(revision 85f20643f5a50d25ca775e64fad72573fcdf8e7d)
+++ uspace/lib/c/include/ipc/clock_ctl.h	(revision 85f20643f5a50d25ca775e64fad72573fcdf8e7d)
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2012 Maurizio Lombardi
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef LIBC_IPC_CLOCK_CTL_H_
+#define LIBC_IPC_CLOCK_CTL_H_
+
+#include <ipc/dev_iface.h>
+
+typedef enum {
+	CLOCK_GET_BATTERY_STATUS = DEV_FIRST_CUSTOM_METHOD,
+} clock_ctl_t;
+
+#endif
+
Index: uspace/lib/c/include/ipc/dev_iface.h
===================================================================
--- uspace/lib/c/include/ipc/dev_iface.h	(revision d11a1811118ec8e5eb8ca4beae291275a4ce36b6)
+++ uspace/lib/c/include/ipc/dev_iface.h	(revision 85f20643f5a50d25ca775e64fad72573fcdf8e7d)
@@ -52,4 +52,7 @@
 	USBHID_DEV_IFACE,
 
+	/** Interface provided by Real Time Clock devices */
+	CLOCK_DEV_IFACE,
+
 	DEV_IFACE_MAX
 } dev_inferface_idx_t;
Index: uspace/lib/c/include/sys/time.h
===================================================================
--- uspace/lib/c/include/sys/time.h	(revision d11a1811118ec8e5eb8ca4beae291275a4ce36b6)
+++ uspace/lib/c/include/sys/time.h	(revision 85f20643f5a50d25ca775e64fad72573fcdf8e7d)
@@ -46,4 +46,13 @@
 typedef uint32_t mseconds_t;
 
+struct tm {
+	int tm_sec;       /* 0 - 59 */
+	int tm_min;       /* 0 - 59 */
+	int tm_hour;      /* 0 - 23 */
+	int tm_mday;      /* 1 - 31 */
+	int tm_mon;       /* 0 - 11 */
+	int tm_year;      /* years since 1900 */
+};
+
 struct timeval {
 	time_t tv_sec;        /* seconds */
Index: uspace/lib/drv/Makefile
===================================================================
--- uspace/lib/drv/Makefile	(revision d11a1811118ec8e5eb8ca4beae291275a4ce36b6)
+++ uspace/lib/drv/Makefile	(revision 85f20643f5a50d25ca775e64fad72573fcdf8e7d)
@@ -44,5 +44,6 @@
 	generic/remote_pci.c \
 	generic/remote_usbhc.c \
-	generic/remote_usbhid.c
+	generic/remote_usbhid.c \
+	generic/remote_clock_dev.c
 
 include $(USPACE_PREFIX)/Makefile.common
Index: uspace/lib/drv/generic/dev_iface.c
===================================================================
--- uspace/lib/drv/generic/dev_iface.c	(revision d11a1811118ec8e5eb8ca4beae291275a4ce36b6)
+++ uspace/lib/drv/generic/dev_iface.c	(revision 85f20643f5a50d25ca775e64fad72573fcdf8e7d)
@@ -41,4 +41,5 @@
 #include "remote_hw_res.h"
 #include "remote_char_dev.h"
+#include "remote_clock_dev.h"
 #include "remote_nic.h"
 #include "remote_usb.h"
@@ -55,5 +56,6 @@
 		&remote_usb_iface,
 		&remote_usbhc_iface,
-		&remote_usbhid_iface
+		&remote_usbhid_iface,
+		&remote_clock_dev_iface,
 	}
 };
Index: uspace/lib/drv/generic/remote_clock_dev.c
===================================================================
--- uspace/lib/drv/generic/remote_clock_dev.c	(revision 85f20643f5a50d25ca775e64fad72573fcdf8e7d)
+++ uspace/lib/drv/generic/remote_clock_dev.c	(revision 85f20643f5a50d25ca775e64fad72573fcdf8e7d)
@@ -0,0 +1,147 @@
+/*
+ * Copyright (c) 2012 Maurizio Lombardi
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup libdrv
+ * @{
+ */
+/** @file
+ */
+
+#include <async.h>
+#include <errno.h>
+#include <time.h>
+
+#include <ops/clock_dev.h>
+#include <ddf/driver.h>
+
+static void remote_clock_time_get(ddf_fun_t *, void *, ipc_callid_t,
+    ipc_call_t *);
+static void remote_clock_time_set(ddf_fun_t *, void *, ipc_callid_t,
+    ipc_call_t *);
+
+/** Remote clock interface operations */
+static remote_iface_func_ptr_t remote_clock_dev_iface_ops[] = {
+	&remote_clock_time_get,
+	&remote_clock_time_set,
+};
+
+/** Remote clock interface structure
+ *
+ * Interface for processing requests from remote clients
+ * addressed by the clock interface.
+ */
+remote_iface_t remote_clock_dev_iface = {
+	.method_count = sizeof(remote_clock_dev_iface_ops) /
+	    sizeof(remote_iface_func_ptr_t),
+	.methods = remote_clock_dev_iface_ops,
+};
+
+/** Process the time_get() request from the remote client
+ *
+ * @param fun   The function from which the time is read
+ * @param ops   The local ops structure
+ */
+static void
+remote_clock_time_get(ddf_fun_t *fun, void *ops, ipc_callid_t callid,
+    ipc_call_t *call)
+{
+	clock_dev_ops_t *clock_dev_ops = (clock_dev_ops_t *) ops;
+	ipc_callid_t cid;
+	struct tm t;
+	int rc;
+	size_t len;
+
+	if (!async_data_read_receive(&cid, &len)) {
+		/* TODO: Handle protocol error */
+		async_answer_0(callid, EINVAL);
+		return;
+	}
+
+	if (!clock_dev_ops->time_get) {
+		/* The driver does not provide the time_get() functionality */
+		async_data_read_finalize(cid, NULL, 0);
+		async_answer_0(callid, ENOTSUP);
+		return;
+	}
+
+	rc = (*clock_dev_ops->time_get)(fun, &t);
+
+	if (rc != EOK) {
+		/* Some error occurred */
+		async_data_read_finalize(cid, NULL, 0);
+		async_answer_0(callid, rc);
+	}
+
+	/* The operation was successful */
+	async_data_read_finalize(cid, &t, sizeof(struct tm));
+	async_answer_1(callid, EOK, rc);
+}
+
+/** Process the write request from the remote client
+ *
+ * @param fun   The function to which the data are written
+ * @param ops   The local ops structure
+ */
+static void remote_clock_time_set(ddf_fun_t *fun, void *ops,
+    ipc_callid_t callid, ipc_call_t *call)
+{
+	clock_dev_ops_t *clock_dev_ops = (clock_dev_ops_t *) ops;
+	int          rc;
+	struct tm    t;
+	ipc_callid_t cid;
+	size_t       len;
+
+	if (!async_data_write_receive(&cid, &len)) {
+		/* TODO: Handle protocol error */
+		async_answer_0(callid, EINVAL);
+		return;
+	}
+
+	if (!clock_dev_ops->time_set) {
+		/* The driver does not support the time_set() functionality */
+		async_data_write_finalize(cid, NULL, 0);
+		async_answer_0(callid, ENOTSUP);
+		return;
+	}
+
+	async_data_write_finalize(cid, &t, sizeof(struct tm));
+
+	rc = (*clock_dev_ops->time_set)(fun, &t);
+	if (rc < 0) {
+		/* Some error occurred */
+		async_answer_0(callid, rc);
+		return;
+	}
+
+	async_answer_1(callid, EOK, rc);
+}
+
+/**
+ * @}
+ */
+
Index: uspace/lib/drv/include/ops/clock_dev.h
===================================================================
--- uspace/lib/drv/include/ops/clock_dev.h	(revision 85f20643f5a50d25ca775e64fad72573fcdf8e7d)
+++ uspace/lib/drv/include/ops/clock_dev.h	(revision 85f20643f5a50d25ca775e64fad72573fcdf8e7d)
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2012 Maurizio Lombardi
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup libdrv
+ * @{
+ */
+/** @file
+ */
+
+#ifndef LIBDRV_OPS_CLOCK_DEV_H_
+#define LIBDRV_OPS_CLOCK_DEV_H_
+
+#include <time.h>
+#include "../ddf/driver.h"
+
+typedef struct {
+	int (*time_get)(ddf_fun_t *, struct tm *);
+	int (*time_set)(ddf_fun_t *, struct tm *);
+} clock_dev_ops_t;
+
+#endif
+
+/**
+ * @}
+ */
Index: uspace/lib/drv/include/remote_clock_dev.h
===================================================================
--- uspace/lib/drv/include/remote_clock_dev.h	(revision 85f20643f5a50d25ca775e64fad72573fcdf8e7d)
+++ uspace/lib/drv/include/remote_clock_dev.h	(revision 85f20643f5a50d25ca775e64fad72573fcdf8e7d)
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2012 Maurizio Lombardi
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup libdrv
+ * @{
+ */
+/** @file
+ */
+
+#ifndef LIBDRV_REMOTE_CLOCK_DEV_H_
+#define LIBDRV_REMOTE_CLOCK_DEV_H_
+
+extern remote_iface_t remote_clock_dev_iface;
+
+#endif
+
+/**
+ * @}
+ */
+
Index: uspace/srv/loc/loc.c
===================================================================
--- uspace/srv/loc/loc.c	(revision d11a1811118ec8e5eb8ca4beae291275a4ce36b6)
+++ uspace/srv/loc/loc.c	(revision 85f20643f5a50d25ca775e64fad72573fcdf8e7d)
@@ -1305,4 +1305,7 @@
 	categ_dir_add_cat(&cdir, cat);
 
+	cat = category_new("clock");
+	categ_dir_add_cat(&cdir, cat);
+
 	cat = category_new("test3");
 	categ_dir_add_cat(&cdir, cat);
