Index: uspace/lib/c/generic/device/hw_res.c
===================================================================
--- uspace/lib/c/generic/device/hw_res.c	(revision a3fcfbab8ada7658810ed4966e92d5dc1f3cfec7)
+++ uspace/lib/c/generic/device/hw_res.c	(revision 6843a9ccc55ea4287771f720d4f1117afbcb5bee)
@@ -42,14 +42,16 @@
 {
 	sysarg_t count = 0;
-	
+
 	async_exch_t *exch = async_exchange_begin(sess);
+	if (exch == NULL)
+		return ENOMEM;
 	int rc = async_req_1_1(exch, DEV_IFACE_ID(HW_RES_DEV_IFACE),
 	    HW_RES_GET_RESOURCE_LIST, &count);
-	
+
 	if (rc != EOK) {
 		async_exchange_end(exch);
 		return rc;
 	}
-	
+
 	size_t size = count * sizeof(hw_resource_t);
 	hw_resource_t *resources = (hw_resource_t *) malloc(size);
@@ -59,16 +61,16 @@
 		return ENOMEM;
 	}
-	
+
 	rc = async_data_read_start(exch, resources, size);
 	async_exchange_end(exch);
-	
+
 	if (rc != EOK) {
 		free(resources);
 		return rc;
 	}
-	
+
 	hw_resources->resources = resources;
 	hw_resources->count = count;
-	
+
 	return EOK;
 }
@@ -77,9 +79,38 @@
 {
 	async_exch_t *exch = async_exchange_begin(sess);
+	if (exch == NULL)
+		return false;
 	int rc = async_req_1_0(exch, DEV_IFACE_ID(HW_RES_DEV_IFACE),
 	    HW_RES_ENABLE_INTERRUPT);
 	async_exchange_end(exch);
-	
+
 	return (rc == EOK);
+}
+
+/**
+ * Setup DMA channel to specified place and mode.
+ * @param channel DMA Channel 1,2,3 for 8 bit transfers, 5,6,7 for 16 bit.
+ * @param pa Physical address of the buffer. Must be < 16MB for 16 bit and < 1MB
+ *           for 8 bit transfers.
+ * @param size DMA buffer size, limited to 64K.
+ * @param mode Mode of the DMA channel:
+ *              - Read or Write
+ *              - Allow automatic reset
+ *              - Use address decrement instead of increment
+ *              - Use SINGLE/BLOCK/ON DEMAND transfer mode
+ * @return Error code.
+ */
+int hw_res_dma_channel_setup(async_sess_t *sess,
+    unsigned channel, uint32_t pa, uint16_t size, uint8_t mode)
+{
+	async_exch_t *exch = async_exchange_begin(sess);
+	if (exch == NULL)
+		return ENOMEM;
+	const uint32_t packed = size | (mode << 16);
+	const int ret = async_req_4_0(exch, DEV_IFACE_ID(HW_RES_DEV_IFACE),
+	    HW_RES_DMA_CHANNEL_SETUP, channel, pa, packed);
+	async_exchange_end(exch);
+
+	return ret;
 }
 
Index: uspace/lib/c/generic/device/hw_res_parsed.c
===================================================================
--- uspace/lib/c/generic/device/hw_res_parsed.c	(revision a3fcfbab8ada7658810ed4966e92d5dc1f3cfec7)
+++ uspace/lib/c/generic/device/hw_res_parsed.c	(revision 6843a9ccc55ea4287771f720d4f1117afbcb5bee)
@@ -38,6 +38,28 @@
 #include <errno.h>
 
-static void hw_res_parse_add_irq(hw_res_list_parsed_t *out, hw_resource_t *res,
-    int flags)
+static void hw_res_parse_add_dma_channel(hw_res_list_parsed_t *out,
+    const hw_resource_t *res, int flags)
+{
+	assert(res);
+	assert((res->type == DMA_CHANNEL_8) || (res->type == DMA_CHANNEL_16));
+	
+	const int channel = (res->type == DMA_CHANNEL_8) ?
+	    res->res.dma_channel.dma8 : res->res.dma_channel.dma16;
+	const size_t count = out->dma_channels.count;
+	const int keep_duplicit = flags & HW_RES_KEEP_DUPLICIT;
+	
+	if (!keep_duplicit) {
+		for (size_t i = 0; i < count; ++i) {
+			if (out->dma_channels.channels[i] == channel)
+				return;
+		}
+	}
+	
+	out->dma_channels.channels[count] = channel;
+	++out->dma_channels.count;
+}
+
+static void hw_res_parse_add_irq(hw_res_list_parsed_t *out,
+    const hw_resource_t *res, int flags)
 {
 	assert(res && (res->type == INTERRUPT));
@@ -59,5 +81,5 @@
 
 static void hw_res_parse_add_io_range(hw_res_list_parsed_t *out,
-    hw_resource_t *res, int flags)
+    const hw_resource_t *res, int flags)
 {
 	assert(res && (res->type == IO_RANGE));
@@ -90,5 +112,5 @@
 
 static void hw_res_parse_add_mem_range(hw_res_list_parsed_t *out,
-    hw_resource_t *res, int flags)
+    const hw_resource_t *res, int flags)
 {
 	assert(res && (res->type == MEM_RANGE));
@@ -132,5 +154,5 @@
  *
  */
-int hw_res_list_parse(hw_resource_list_t *hw_resources,
+int hw_res_list_parse(const hw_resource_list_t *hw_resources,
     hw_res_list_parsed_t *out, int flags)
 {
@@ -141,11 +163,17 @@
 	hw_res_list_parsed_clean(out);
 	
-	out->irqs.irqs = malloc(res_count * sizeof(int));
-	out->io_ranges.ranges = malloc(res_count * sizeof(io_range_t));
-	out->mem_ranges.ranges = malloc(res_count * sizeof(mem_range_t));
+	out->irqs.irqs = calloc(res_count, sizeof(int));
+	out->dma_channels.channels = calloc(res_count, sizeof(int));
+	out->io_ranges.ranges = calloc(res_count, sizeof(io_range_t));
+	out->mem_ranges.ranges = calloc(res_count, sizeof(mem_range_t));
+	if (!out->irqs.irqs || !out->dma_channels.channels ||
+	    !out->io_ranges.ranges || !out->mem_ranges.ranges) {
+		hw_res_list_parsed_clean(out);
+		return ENOMEM;
+	}
 	
 	for (size_t i = 0; i < res_count; ++i) {
-		hw_resource_t *resource = &(hw_resources->resources[i]);
-		
+		const hw_resource_t *resource = &(hw_resources->resources[i]);
+
 		switch (resource->type) {
 		case INTERRUPT:
@@ -158,9 +186,14 @@
 			hw_res_parse_add_mem_range(out, resource, flags);
 			break;
+		case DMA_CHANNEL_8:
+		case DMA_CHANNEL_16:
+			hw_res_parse_add_dma_channel(out, resource, flags);
+			break;
 		default:
+			hw_res_list_parsed_clean(out);
 			return EINVAL;
 		}
 	}
-	
+
 	return EOK;
 };
Index: uspace/lib/c/include/device/hw_res_parsed.h
===================================================================
--- uspace/lib/c/include/device/hw_res_parsed.h	(revision a3fcfbab8ada7658810ed4966e92d5dc1f3cfec7)
+++ uspace/lib/c/include/device/hw_res_parsed.h	(revision 6843a9ccc55ea4287771f720d4f1117afbcb5bee)
@@ -100,4 +100,7 @@
 	/** List of IRQs */
 	irq_list_t irqs;
+
+	/** List of DMA channels */
+	dma_list_t dma_channels;
 	
 	/** List of DMA channels */
@@ -139,5 +142,6 @@
 }
 
-extern int hw_res_list_parse(hw_resource_list_t *, hw_res_list_parsed_t *, int);
+extern int hw_res_list_parse(
+    const hw_resource_list_t *, hw_res_list_parsed_t *, int);
 extern int hw_res_get_list_parsed(async_sess_t *, hw_res_list_parsed_t *, int);
 
Index: uspace/lib/c/include/ipc/dev_iface.h
===================================================================
--- uspace/lib/c/include/ipc/dev_iface.h	(revision a3fcfbab8ada7658810ed4966e92d5dc1f3cfec7)
+++ uspace/lib/c/include/ipc/dev_iface.h	(revision 6843a9ccc55ea4287771f720d4f1117afbcb5bee)
@@ -36,4 +36,10 @@
 typedef enum {
 	HW_RES_DEV_IFACE = 0,
+
+	/** Audio device mixer interface */
+	AUDIO_MIXER_IFACE,
+	/** Audio device pcm buffer interface */
+	AUDIO_PCM_BUFFER_IFACE,
+
 	/** Character device interface */
 	CHAR_DEV_IFACE,
