Index: uspace/drv/audio/sb16/Makefile
===================================================================
--- uspace/drv/audio/sb16/Makefile	(revision 53738d363dfe64f2c2f3ef4b2a9212eda500f333)
+++ uspace/drv/audio/sb16/Makefile	(revision 7a6934020639a8d79ebb3265af1c644befa8b482)
@@ -38,5 +38,6 @@
 
 SOURCES = \
-	main.c
+	main.c \
+	sb16.c
 
 include $(USPACE_PREFIX)/Makefile.common
Index: uspace/drv/audio/sb16/ddf_log.h
===================================================================
--- uspace/drv/audio/sb16/ddf_log.h	(revision 53738d363dfe64f2c2f3ef4b2a9212eda500f333)
+++ uspace/drv/audio/sb16/ddf_log.h	(revision 7a6934020639a8d79ebb3265af1c644befa8b482)
@@ -40,5 +40,5 @@
 #define ddf_log_fatal(msg...) ddf_msg(LVL_FATAL, msg)
 #define ddf_log_error(msg...) ddf_msg(LVL_ERROR, msg)
-#define ddf_log_warning(msg...) ddf_msg(LVL_WARNING, msg)
+#define ddf_log_warning(msg...) ddf_msg(LVL_WARN, msg)
 #define ddf_log_note(msg...) ddf_msg(LVL_NOTE, msg)
 #define ddf_log_debug(msg...) ddf_msg(LVL_DEBUG, msg)
Index: uspace/drv/audio/sb16/main.c
===================================================================
--- uspace/drv/audio/sb16/main.c	(revision 53738d363dfe64f2c2f3ef4b2a9212eda500f333)
+++ uspace/drv/audio/sb16/main.c	(revision 7a6934020639a8d79ebb3265af1c644befa8b482)
@@ -41,6 +41,5 @@
 #include <stdio.h>
 #include <errno.h>
-
-//#include <str_error.h>
+#include <str_error.h>
 
 #include "ddf_log.h"
@@ -78,4 +77,9 @@
 }
 /*----------------------------------------------------------------------------*/
+static void irq_handler(ddf_dev_t *dev, ipc_callid_t iid, ipc_call_t *call)
+{
+	ddf_log_note("SB16 IRQ handler.\n");
+}
+/*----------------------------------------------------------------------------*/
 /** Initializes a new ddf driver instance of SB16.
  *
@@ -85,12 +89,84 @@
 static int sb_add_device(ddf_dev_t *device)
 {
+#define CHECK_RET_FREE_RETURN(ret, msg...) \
+if (ret != EOK) { \
+	free(soft_state); \
+	ddf_log_error(msg); \
+	return ret; \
+} else (void)0
+
 	assert(device);
+
+	sb16_drv_t *soft_state = malloc(sizeof(sb16_drv_t));
+	int ret = soft_state ? EOK : ENOMEM;
+	CHECK_RET_FREE_RETURN(ret, "Failed to allocate sb16 structure.\n");
+
 	uintptr_t sb_regs = 0, mpu_regs = 0;
 	size_t sb_regs_size = 0, mpu_regs_size = 0;
 	int irq = 0;
-	int ret = sb_get_res(device, &sb_regs, &sb_regs_size, &mpu_regs,
+
+	ret = sb_get_res(device, &sb_regs, &sb_regs_size, &mpu_regs,
 	    &mpu_regs_size, &irq);
-
-	return ret;
+	CHECK_RET_FREE_RETURN(ret,
+	    "Failed to get resources: %s.\n", str_error(ret));
+
+	irq_code_t *irq_code = sb16_irq_code();
+	ret = register_interrupt_handler(device, irq, irq_handler, irq_code);
+	CHECK_RET_FREE_RETURN(ret,
+	    "Failed to register irq handler: %s.\n", str_error(ret));
+
+	ddf_fun_t *dsp_fun = NULL, *mixer_fun = NULL;
+#define CHECK_RET_UNREG_DEST_RETURN(ret, msg...) \
+if (ret != EOK) { \
+	ddf_log_error(msg); \
+	if (dsp_fun) \
+		ddf_fun_destroy(dsp_fun); \
+	if (mixer_fun) \
+		ddf_fun_destroy(mixer_fun); \
+	free(soft_state); \
+	unregister_interrupt_handler(device, irq); \
+	return ret; \
+} else (void)0
+	dsp_fun = ddf_fun_create(device, fun_exposed, "dsp");
+	ret = dsp_fun ? EOK : ENOMEM;
+	CHECK_RET_UNREG_DEST_RETURN(ret, "Failed to create dsp function.");
+
+	ret = ddf_fun_bind(dsp_fun);
+	CHECK_RET_UNREG_DEST_RETURN(ret,
+	    "Failed to bind dsp function: %s.\n", str_error(ret));
+	dsp_fun->driver_data = soft_state;
+
+	mixer_fun = ddf_fun_create(device, fun_exposed, "mixer");
+	ret = dsp_fun ? EOK : ENOMEM;
+	CHECK_RET_UNREG_DEST_RETURN(ret, "Failed to create mixer function.");
+
+	ret = ddf_fun_bind(mixer_fun);
+	CHECK_RET_UNREG_DEST_RETURN(ret,
+	    "Failed to bind mixer function: %s.\n", str_error(ret));
+	mixer_fun->driver_data = soft_state;
+
+	ret = sb16_init_sb16(soft_state, (void*)sb_regs, sb_regs_size);
+	CHECK_RET_UNREG_DEST_RETURN(ret,
+	    "Failed to init sb16 driver: %s.\n", str_error(ret));
+
+	ret = sb16_init_mpu(soft_state, (void*)mpu_regs, mpu_regs_size);
+	if (ret == EOK) {
+		ddf_fun_t *mpu_fun =
+		    ddf_fun_create(device, fun_exposed, "midi");
+		if (mpu_fun) {
+			ret = ddf_fun_bind(mpu_fun);
+			if (ret != EOK)
+				ddf_log_error(
+				    "Failed to bind midi function: %s.\n",
+				    str_error(ret));
+		} else {
+			ddf_log_error("Failed to create midi function.\n");
+		}
+	} else {
+	    ddf_log_warning("Failed to init mpu driver: %s.\n", str_error(ret));
+	}
+
+	/* MPU state does not matter */
+	return EOK;
 }
 /*----------------------------------------------------------------------------*/
Index: uspace/drv/audio/sb16/sb16.c
===================================================================
--- uspace/drv/audio/sb16/sb16.c	(revision 7a6934020639a8d79ebb3265af1c644befa8b482)
+++ uspace/drv/audio/sb16/sb16.c	(revision 7a6934020639a8d79ebb3265af1c644befa8b482)
@@ -0,0 +1,57 @@
+/*
+ * 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.
+ */
+
+#include <errno.h>
+
+#include "sb16.h"
+
+/* ISA interrupts should be edge-triggered so there should be no need for
+ * irq code magic */
+static const irq_cmd_t irq_cmds[] = {{ .cmd = CMD_ACCEPT }};
+static const irq_code_t irq_code =
+    { .cmdcount = 1, .cmds = (irq_cmd_t*)irq_cmds };
+
+/*----------------------------------------------------------------------------*/
+irq_code_t * sb16_irq_code(void)
+{
+	return (irq_code_t*)&irq_code;
+}
+/*----------------------------------------------------------------------------*/
+int sb16_init_sb16(sb16_drv_t *drv, void *regs, size_t size)
+{
+	// TODO Setup registers
+	// TODO Initialize dsp: get version number
+	// TODO Initialize dsp: reset DSP
+	// TODO Initialize mixer
+	return EOK;
+}
+/*----------------------------------------------------------------------------*/
+int sb16_init_mpu(sb16_drv_t *drv, void *regs, size_t size)
+{
+	return ENOTSUP;
+}
Index: uspace/drv/audio/sb16/sb16.h
===================================================================
--- uspace/drv/audio/sb16/sb16.h	(revision 53738d363dfe64f2c2f3ef4b2a9212eda500f333)
+++ uspace/drv/audio/sb16/sb16.h	(revision 7a6934020639a8d79ebb3265af1c644befa8b482)
@@ -37,4 +37,5 @@
 
 #include <ddf/driver.h>
+#include <ddi.h>
 #include "registers.h"
 
@@ -44,4 +45,5 @@
 } sb16_drv_t;
 
+irq_code_t * sb16_irq_code(void);
 int sb16_init_sb16(sb16_drv_t *drv, void *regs, size_t size);
 int sb16_init_mpu(sb16_drv_t *drv, void *regs, size_t size);
