Index: uspace/drv/char/i8042/Makefile
===================================================================
--- uspace/drv/char/i8042/Makefile	(revision f44ba92cca7ecb486c01e44a35828c764b333a15)
+++ uspace/drv/char/i8042/Makefile	(revision ee163b3f91b170b746f3137b84e988e62e4bc0bc)
@@ -34,5 +34,6 @@
 
 SOURCES = \
-	i8042.c
+	i8042.c \
+	main.c
 
 include $(USPACE_PREFIX)/Makefile.common
Index: uspace/drv/char/i8042/i8042.c
===================================================================
--- uspace/drv/char/i8042/i8042.c	(revision f44ba92cca7ecb486c01e44a35828c764b333a15)
+++ uspace/drv/char/i8042/i8042.c	(revision ee163b3f91b170b746f3137b84e988e62e4bc0bc)
@@ -42,8 +42,11 @@
 #include <async.h>
 #include <unistd.h>
-#include <sysinfo.h>
 #include <stdio.h>
 #include <errno.h>
+#include <str_error.h>
 #include <inttypes.h>
+#include <ddf/log.h>
+#include <ddf/interrupt.h>
+
 #include "i8042.h"
 
@@ -67,6 +70,5 @@
 #define i8042_KBD_TRANSLATE	0x40
 
-
-static irq_cmd_t i8042_cmds[] = {
+static const irq_cmd_t i8042_cmds[] = {
 	{
 		.cmd = CMD_PIO_READ_8,
@@ -95,12 +97,7 @@
 };
 
-static irq_code_t i8042_kbd = {
-	sizeof(i8042_cmds) / sizeof(irq_cmd_t),
-	i8042_cmds
-};
-
-static i8042_dev_t device;
-
-static void wait_ready(i8042_dev_t *dev)
+static i8042_t device;
+
+static void wait_ready(i8042_t *dev)
 {
 	assert(dev);
@@ -108,73 +105,52 @@
 }
 
-static void i8042_irq_handler(ipc_callid_t iid, ipc_call_t *call);
+static void i8042_irq_handler(ddf_dev_t *dev,
+    ipc_callid_t iid, ipc_call_t *call);
 static void i8042_connection(ipc_callid_t iid, ipc_call_t *icall, void *arg);
-static int i8042_init(i8042_dev_t *dev);
-static void i8042_port_write(i8042_dev_t *dev, int devid, uint8_t data);
-
-
-int main(int argc, char *argv[])
-{
-	printf(NAME ": i8042 PS/2 port driver\n");
-
-	int rc = loc_server_register(NAME, i8042_connection);
-	if (rc < 0) {
-		printf(NAME ": Unable to register server.\n");
-		return rc;
-	}
-
-	if (i8042_init(&device) != EOK)
+static void i8042_port_write(i8042_t *dev, int devid, uint8_t data);
+
+int i8042_init(i8042_t *dev, void *regs, size_t reg_size, int irq_kbd,
+    int irq_mouse, ddf_dev_t *ddf_dev)
+{
+	assert(ddf_dev);
+	assert(dev);
+
+	if (reg_size < sizeof(i8042_regs_t))
+		return EINVAL;
+
+	if (pio_enable(regs, sizeof(i8042_regs_t), (void**)&dev->regs) != 0)
 		return -1;
 
-	for (int i = 0; i < MAX_DEVS; i++) {
-		device.port[i].client_sess = NULL;
-
-		static const char *names[MAX_DEVS] = {
-		    NAMESPACE "/ps2a", NAMESPACE "/ps2b"};
-		rc = loc_service_register(names[i], &device.port[i].service_id);
-		if (rc != EOK) {
-			printf(NAME ": Unable to register device %s.\n",
-			    names[i]);
-			return rc;
-		}
-		printf(NAME ": Registered device %s\n", names[i]);
-	}
-
-	printf(NAME ": Accepting connections\n");
-	task_retval(0);
-	async_manager();
-
-	/* Not reached */
-	return 0;
-}
-
-static int i8042_init(i8042_dev_t *dev)
-{
-	static uintptr_t i8042_physical;
-	static uintptr_t i8042_kernel;
-	assert(dev);
-	if (sysinfo_get_value("i8042.address.physical", &i8042_physical) != EOK)
-		return -1;
-	
-	if (sysinfo_get_value("i8042.address.kernel", &i8042_kernel) != EOK)
-		return -1;
-	
-	void *vaddr;
-	if (pio_enable((void *) i8042_physical, sizeof(i8042_regs_t), &vaddr) != 0)
-		return -1;
-	
-	dev->regs = vaddr;
-	
-	sysarg_t inr_a;
-	sysarg_t inr_b;
-	
-	if (sysinfo_get_value("i8042.inr_a", &inr_a) != EOK)
-		return -1;
-	
-	if (sysinfo_get_value("i8042.inr_b", &inr_b) != EOK)
-		return -1;
-	
-	async_set_interrupt_received(i8042_irq_handler);
-	
+	dev->kbd_fun = ddf_fun_create(ddf_dev, fun_exposed, "ps2a");
+	if (!dev->kbd_fun)
+		return ENOMEM;
+
+	dev->mouse_fun = ddf_fun_create(ddf_dev, fun_exposed, "ps2b");
+	if (!dev->mouse_fun) {
+		ddf_fun_destroy(dev->kbd_fun);
+		return ENOMEM;
+	}
+
+#define CHECK_RET_DESTROY(ret, msg...) \
+if  (ret != EOK) { \
+	ddf_msg(LVL_ERROR, msg); \
+	if (dev->kbd_fun) { \
+		dev->kbd_fun->driver_data = NULL; \
+		ddf_fun_destroy(dev->kbd_fun); \
+	} \
+	if (dev->mouse_fun) { \
+		dev->mouse_fun->driver_data = NULL; \
+		ddf_fun_destroy(dev->mouse_fun); \
+	} \
+} else (void)0
+
+	int ret = ddf_fun_bind(dev->kbd_fun);
+	CHECK_RET_DESTROY(ret,
+	    "Failed to bind keyboard function: %s.\n", str_error(ret));
+
+	ret = ddf_fun_bind(dev->mouse_fun);
+	CHECK_RET_DESTROY(ret,
+	    "Failed to bind mouse function: %s.\n", str_error(ret));
+
 	/* Disable kbd and aux */
 	wait_ready(dev);
@@ -187,10 +163,49 @@
 		(void) pio_read_8(&dev->regs->data);
 
-	i8042_kbd.cmds[0].addr = (void *) &((i8042_regs_t *) i8042_kernel)->status;
-	i8042_kbd.cmds[3].addr = (void *) &((i8042_regs_t *) i8042_kernel)->data;
-	register_irq(inr_a, device_assign_devno(), 0, &i8042_kbd);
-	register_irq(inr_b, device_assign_devno(), 0, &i8042_kbd);
-	printf("%s: registered for interrupts %" PRIun " and %" PRIun "\n",
-	    NAME, inr_a, inr_b);
+#define CHECK_RET_UNBIND_DESTROY(ret, msg...) \
+if  (ret != EOK) { \
+	ddf_msg(LVL_ERROR, msg); \
+	if (dev->kbd_fun) { \
+		ddf_fun_unbind(dev->kbd_fun); \
+		dev->kbd_fun->driver_data = NULL; \
+		ddf_fun_destroy(dev->kbd_fun); \
+	} \
+	if (dev->mouse_fun) { \
+		ddf_fun_unbind(dev->mouse_fun); \
+		dev->mouse_fun->driver_data = NULL; \
+		ddf_fun_destroy(dev->mouse_fun); \
+	} \
+} else (void)0
+	const size_t cmd_count = sizeof(i8042_cmds) / sizeof(irq_cmd_t);
+	irq_cmd_t cmds[cmd_count];
+	memcpy(cmds, i8042_cmds, sizeof(i8042_cmds));
+	cmds[0].addr = (void *) &dev->regs->status;
+	cmds[3].addr = (void *) &dev->regs->data;
+
+	irq_code_t irq_code = { .cmdcount = cmd_count, .cmds = cmds };
+	ddf_msg(LVL_DEBUG,
+	    "Registering interrupt handler for device %s on irq %d.\n",
+	    ddf_dev->name, irq_kbd);
+	ret = register_interrupt_handler(ddf_dev, irq_kbd, i8042_irq_handler,
+	    &irq_code);
+	CHECK_RET_UNBIND_DESTROY(ret,
+	    "Failed set handler for kbd: %s.\n", str_error(ret));
+
+	ddf_msg(LVL_DEBUG,
+	    "Registering interrupt handler for device %s on irq %d.\n",
+	    ddf_dev->name, irq_mouse);
+	ret = register_interrupt_handler(ddf_dev, irq_mouse, i8042_irq_handler,
+	    &irq_code);
+	CHECK_RET_UNBIND_DESTROY(ret,
+	    "Failed set handler for mouse: %s.\n", str_error(ret));
+
+	ret = ddf_fun_add_to_category(dev->kbd_fun, "keyboard");
+	if (ret != EOK)
+		ddf_msg(LVL_WARN, "Failed to register kbd fun to category.\n");
+	ret = ddf_fun_add_to_category(dev->mouse_fun, "mouse");
+	if (ret != EOK)
+		ddf_msg(LVL_WARN, "Failed to register mouse fun to category.\n");
+
+	// TODO: Don't rely on kernel enabling interrupts do it yourself.
 
 	wait_ready(dev);
@@ -200,5 +215,8 @@
 	    i8042_AUX_IE);
 
-	return 0;
+	// TODO: Plug in connection.
+
+	return ret;
+	(void)i8042_connection;
 }
 
@@ -271,6 +289,7 @@
 }
 
-void i8042_port_write(i8042_dev_t *dev, int devid, uint8_t data)
-{
+void i8042_port_write(i8042_t *dev, int devid, uint8_t data)
+{
+
 	assert(dev);
 	if (devid == DEVID_AUX) {
@@ -282,23 +301,23 @@
 }
 
-static void i8042_irq_handler(ipc_callid_t iid, ipc_call_t *call)
-{
-	int status, data;
-	int devid;
-
-	status = IPC_GET_ARG1(*call);
-	data = IPC_GET_ARG2(*call);
-
-	if ((status & i8042_AUX_DATA)) {
-		devid = DEVID_AUX;
-	} else {
-		devid = DEVID_PRI;
-	}
+void i8042_irq_handler(ddf_dev_t *dev, ipc_callid_t iid, ipc_call_t *call)
+{
+	ddf_msg(LVL_FATAL, "IRQ!!!.\n");
+	if (!dev || !dev->driver_data)
+		return;
+
+	const int status = IPC_GET_ARG1(*call);
+	const int data = IPC_GET_ARG2(*call);
+	const int devid = (status & i8042_AUX_DATA) ? DEVID_AUX : DEVID_PRI;
 
 	if (device.port[devid].client_sess != NULL) {
 		async_exch_t *exch =
 		    async_exchange_begin(device.port[devid].client_sess);
-		async_msg_1(exch, IPC_FIRST_USER_METHOD, data);
-		async_exchange_end(exch);
+		if (exch) {
+			async_msg_1(exch, IPC_FIRST_USER_METHOD, data);
+			async_exchange_end(exch);
+		}
+	} else {
+		ddf_msg(LVL_WARN, "No client session.\n");
 	}
 }
Index: uspace/drv/char/i8042/i8042.h
===================================================================
--- uspace/drv/char/i8042/i8042.h	(revision f44ba92cca7ecb486c01e44a35828c764b333a15)
+++ uspace/drv/char/i8042/i8042.h	(revision ee163b3f91b170b746f3137b84e988e62e4bc0bc)
@@ -42,4 +42,5 @@
 #include <libarch/ddi.h>
 #include <async.h>
+#include <ddf/driver.h>
 
 /** i8042 HW I/O interface */
@@ -65,8 +66,11 @@
 	i8042_regs_t *regs;
 	i8042_port_t port[MAX_DEVS];
-} i8042_dev_t;
+	ddf_fun_t *kbd_fun;
+	ddf_fun_t *mouse_fun;
+} i8042_t;
+
+int i8042_init(i8042_t *, void *, size_t, int, int, ddf_dev_t *);
 
 #endif
-
 /**
  * @}
Index: uspace/drv/char/i8042/i8042.ma
===================================================================
--- uspace/drv/char/i8042/i8042.ma	(revision ee163b3f91b170b746f3137b84e988e62e4bc0bc)
+++ uspace/drv/char/i8042/i8042.ma	(revision ee163b3f91b170b746f3137b84e988e62e4bc0bc)
@@ -0,0 +1,1 @@
+100 isa/i8042
Index: uspace/drv/char/i8042/main.c
===================================================================
--- uspace/drv/char/i8042/main.c	(revision ee163b3f91b170b746f3137b84e988e62e4bc0bc)
+++ uspace/drv/char/i8042/main.c	(revision ee163b3f91b170b746f3137b84e988e62e4bc0bc)
@@ -0,0 +1,166 @@
+/*
+ * Copyright (c) 2011 Jan Vesely
+ * 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 drvi8042
+ * @{
+ */
+/** @file
+ * @brief i8042 driver DDF bits.
+ */
+
+#include <libarch/inttypes.h>
+#include <ddf/driver.h>
+#include <devman.h>
+#include <device/hw_res_parsed.h>
+#include <errno.h>
+#include <str_error.h>
+#include <ddf/log.h>
+#include <stdio.h>
+
+#include "i8042.h"
+
+#define NAME "i8042"
+
+static int get_my_registers(const ddf_dev_t *dev,
+    uintptr_t *io_reg_address, size_t *io_reg_size, int *kbd, int *mouse);
+
+static int i8042_dev_add(ddf_dev_t *device);
+
+static driver_ops_t i8042_driver_ops = {
+	.dev_add = i8042_dev_add,
+};
+
+static driver_t i8042_driver = {
+	.name = NAME,
+	.driver_ops = &i8042_driver_ops
+};
+
+/** Initialize global driver structures (NONE).
+ *
+ * @param[in] argc Nmber of arguments in argv vector (ignored).
+ * @param[in] argv Cmdline argument vector (ignored).
+ * @return Error code.
+ *
+ * Driver debug level is set here.
+ */
+int main(int argc, char *argv[])
+{
+	printf(NAME ": HelenOS ps/2 driver.\n");
+	ddf_log_init(NAME, LVL_DEBUG2);
+	return ddf_driver_main(&i8042_driver);
+}
+
+/** Initialize a new ddf driver instance of i8042 driver
+ *
+ * @param[in] device DDF instance of the device to initialize.
+ * @return Error code.
+ */
+static int i8042_dev_add(ddf_dev_t *device)
+{
+	if (!device)
+		return EINVAL;
+
+#define CHECK_RET_RETURN(ret, message...) \
+if (ret != EOK) { \
+	ddf_msg(LVL_ERROR, message); \
+	return ret; \
+} else (void)0
+
+	uintptr_t io_regs = 0;
+	size_t io_size = 0;
+	int kbd = 0, mouse = 0;
+
+	int ret = get_my_registers(device, &io_regs, &io_size, &kbd, &mouse);
+	CHECK_RET_RETURN(ret,
+	    "Failed to get registers: %s.\n", str_error(ret));
+	ddf_msg(LVL_DEBUG,
+	    "I/O regs at %p (size %zuB), IRQ kbd %d, IRQ mouse %d.\n",
+	    (void *) io_regs, io_size, kbd, mouse);
+
+	i8042_t *i8042 = ddf_dev_data_alloc(device, sizeof(i8042_t));
+	ret = (i8042 == NULL) ? ENOMEM : EOK;
+	CHECK_RET_RETURN(ret, "Failed to allocate i8042 driver instance.\n");
+
+	ret = i8042_init(i8042, (void*)io_regs, io_size, kbd, mouse, device);
+	CHECK_RET_RETURN(ret,
+	    "Failed to initialize i8042 driver: %s.\n", str_error(ret));
+
+	ddf_msg(LVL_NOTE, "Controlling '%s' (%" PRIun ").\n",
+	    device->name, device->handle);
+	return EOK;
+}
+
+/** Get address of I/O registers.
+ *
+ * @param[in] dev Device asking for the addresses.
+ * @param[out] io_reg_address Base address of the memory range.
+ * @param[out] io_reg_size Size of the memory range.
+ * @return Error code.
+ */
+int get_my_registers(const ddf_dev_t *dev, uintptr_t *io_reg_address,
+    size_t *io_reg_size, int *kbd_irq, int *mouse_irq)
+{
+	assert(dev);
+
+	async_sess_t *parent_sess =
+	    devman_parent_device_connect(EXCHANGE_SERIALIZE, dev->handle,
+	    IPC_FLAG_BLOCKING);
+	if (!parent_sess)
+		return ENOMEM;
+
+	hw_res_list_parsed_t hw_resources;
+	hw_res_list_parsed_init(&hw_resources);
+	const int ret = hw_res_get_list_parsed(parent_sess, &hw_resources, 0);
+	async_hangup(parent_sess);
+	if (ret != EOK) {
+		return ret;
+	}
+
+	if (hw_resources.irqs.count != 2 || hw_resources.io_ranges.count != 1) {
+		hw_res_list_parsed_clean(&hw_resources);
+		return EINVAL;
+	}
+
+	if (io_reg_address)
+		*io_reg_address = hw_resources.io_ranges.ranges[0].address;
+
+	if (io_reg_size)
+		*io_reg_size = hw_resources.io_ranges.ranges[0].size;
+
+	if (kbd_irq)
+		*kbd_irq = hw_resources.irqs.irqs[0];
+
+	if (mouse_irq)
+		*mouse_irq = hw_resources.irqs.irqs[1];
+
+	hw_res_list_parsed_clean(&hw_resources);
+	return EOK;
+}
+
+/**
+ * @}
+ */
