Index: uspace/drv/bus/isa/Makefile
===================================================================
--- uspace/drv/bus/isa/Makefile	(revision fbcdeb887f643e4a875e51120a2ddbf6fe35e4b3)
+++ uspace/drv/bus/isa/Makefile	(revision fe5e9629448f7d1befa73d7c974f8cedf7bfcbcd)
@@ -1,4 +1,5 @@
 #
 # Copyright (c) 2010 Lenka Trochtova
+# Copyright (c) 2011 Jan Vesely
 # All rights reserved.
 #
@@ -33,4 +34,5 @@
 
 SOURCES = \
+	i8237.c \
 	isa.c
 
Index: uspace/drv/bus/isa/i8237.c
===================================================================
--- uspace/drv/bus/isa/i8237.c	(revision fe5e9629448f7d1befa73d7c974f8cedf7bfcbcd)
+++ uspace/drv/bus/isa/i8237.c	(revision fe5e9629448f7d1befa73d7c974f8cedf7bfcbcd)
@@ -0,0 +1,430 @@
+/*
+ * 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 isa
+ * @{
+ */
+
+/** @file
+ * @brief DMA controller management
+ */
+
+#include <assert.h>
+#include <bool.h>
+#include <errno.h>
+#include <fibril_synch.h>
+#include <ddi.h>
+#include <libarch/ddi.h>
+#include <ddf/log.h>
+#include "i8237.h"
+
+/** DMA Slave controller I/O Address. */
+#define DMA_CONTROLLER_FIRST_BASE  ((void *) 0x00)
+
+/** DMA Master controller I/O Address. */
+#define DMA_CONTROLLER_SECOND_BASE  ((void *) 0xc0)
+
+/** Shared DMA page address register I/O address. */
+#define DMA_CONTROLLER_PAGE_BASE  ((void *) 0x81)
+
+#define DMA_STATUS_REQ(x)       (1 << (((x) % 4) + 4))
+#define DMA_STATUS_COMPLETE(x)  (1 << ((x) % 4))
+
+/** http://wiki.osdev.org/DMA: The only bit that works is COND (bit 2) */
+#define DMA_COMMAND_COND  (1 << 2)  /**< Disables DMA controller */
+
+#define DMA_SINGLE_MASK_CHAN_SEL_MASK   0x03
+#define DMA_SINGLE_MASK_CHAN_SEL_SHIFT  0
+
+#define DMA_SINGLE_MASK_CHAN_TO_REG(x) \
+	(((x) & DMA_SINGLE_MASK_CHAN_SEL_MASK) << DMA_SINGLE_MASK_CHAN_SEL_SHIFT)
+
+#define DMA_SINGLE_MASK_MASKED_FLAG  (1 << 2)
+
+#define DMA_MODE_CHAN_SELECT_MASK   0x03
+#define DMA_MODE_CHAN_SELECT_SHIFT  0
+
+#define DMA_MODE_CHAN_TO_REG(x) \
+	(((x) & DMA_MODE_CHAN_SELECT_MASK) << DMA_MODE_CHAN_SELECT_SHIFT)
+
+#define DMA_MODE_CHAN_TRA_MASK       0x03
+#define DMA_MODE_CHAN_TRA_SHIFT      2
+#define DMA_MODE_CHAN_TRA_SELF_TEST  0
+#define DMA_MODE_CHAN_TRA_WRITE      0x01
+#define DMA_MODE_CHAN_TRA_READ       0x02
+
+#define DMA_MODE_CHAN_AUTO_FLAG  (1 << 4)
+#define DMA_MODE_CHAN_DOWN_FLAG  (1 << 5)
+
+#define DMA_MODE_CHAN_MODE_MASK     0x03
+#define DMA_MODE_CHAN_MODE_SHIFT    6
+#define DMA_MODE_CHAN_MODE_DEMAND   0
+#define DMA_MODE_CHAN_MODE_SINGLE   1
+#define DMA_MODE_CHAN_MODE_BLOCK    2
+#define DMA_MODE_CHAN_MODE_CASCADE  3
+
+#define DMA_MULTI_MASK_CHAN(x)  (1 << ((x) % 4))
+
+typedef struct {
+	uint8_t channel_start0;
+	uint8_t channel_count0;
+	uint8_t channel_start1;
+	uint8_t channel_count1;
+	uint8_t channel_start2;
+	uint8_t channel_count2;
+	uint8_t channel_start3;
+	uint8_t channel_count3;
+	
+	uint8_t command_status;
+	
+	/** Memory to memory transfers, NOT implemented on PCs */
+	uint8_t request;
+	uint8_t single_mask;
+	uint8_t mode;
+	uint8_t flip_flop;
+	
+	/*
+	 * Master reset sets Flip-Flop low, clears status,
+	 * sets all mask bits on.
+	 *
+	 * Intermediate is not implemented on PCs.
+	 *
+	 */
+	uint8_t master_reset;
+	uint8_t mask_reset;
+	uint8_t multi_mask;
+} dma_controller_regs_first_t;
+
+typedef struct {
+	uint8_t channel_start4;
+	uint8_t reserved0;
+	uint8_t channel_count4;
+	uint8_t reserved1;
+	uint8_t channel_start5;
+	uint8_t reserved2;
+	uint8_t channel_count5;
+	uint8_t reserved3;
+	uint8_t channel_start6;
+	uint8_t reserved4;
+	uint8_t channel_count6;
+	uint8_t reserved5;
+	uint8_t channel_start7;
+	uint8_t reserved6;
+	uint8_t channel_count7;
+	
+	uint8_t command_status;
+	uint8_t reserved8;
+	uint8_t request;
+	uint8_t reserved9;
+	uint8_t single_mask;
+	uint8_t reserveda;
+	uint8_t mode;
+	uint8_t reservedb;
+	uint8_t flip_flop;
+	uint8_t reservedc;
+	uint8_t master_reset;
+	uint8_t reservedd;
+	uint8_t multi_mask;
+} dma_controller_regs_second_t;
+
+typedef struct {
+	uint8_t channel2;
+	uint8_t channel3;
+	uint8_t channel1;
+	uint8_t reserved0;
+	uint8_t reserved1;
+	uint8_t reserved2;
+	uint8_t channel0;
+	uint8_t reserved3;
+	uint8_t channel6;
+	uint8_t channel7;
+	uint8_t channel5;
+	uint8_t reserved4;
+	uint8_t reserved5;
+	uint8_t reserved6;
+	uint8_t channel4;
+} dma_page_regs_t;
+
+/** Addresses needed to setup a DMA channel. */
+typedef struct {
+	ioport8_t *offset_reg_address;
+	ioport8_t *size_reg_address;
+	ioport8_t *page_reg_address;
+	ioport8_t *single_mask_address;
+	ioport8_t *mode_address;
+	ioport8_t *flip_flop_address;
+} dma_channel_t;
+
+typedef struct {
+	dma_channel_t channels[8];
+	dma_page_regs_t *page_table;
+	dma_controller_regs_first_t *first;
+	dma_controller_regs_second_t *second;
+	bool initialized;
+} dma_controller_t;
+
+static fibril_mutex_t guard = FIBRIL_MUTEX_INITIALIZER(guard);
+
+/** Standard i8237 DMA controller.
+ *
+ * http://zet.aluzina.org/index.php/8237_DMA_controller#DMA_Channel_Registers
+ *
+ */
+static dma_controller_t controller_8237 = {
+	.channels = {
+		/* The first chip 8-bit */
+		{
+			(uint8_t *) 0x00,
+			(uint8_t *) 0x01,
+			(uint8_t *) 0x87,
+			(uint8_t *) 0x0a,
+			(uint8_t *) 0x0b,
+			(uint8_t *) 0x0c,
+		},
+		{
+			(uint8_t *) 0x02,
+			(uint8_t *) 0x03,
+			(uint8_t *) 0x83,
+			(uint8_t *) 0x0a,
+			(uint8_t *) 0x0b,
+			(uint8_t *) 0x0c,
+		},
+		{
+			(uint8_t *) 0x04,
+			(uint8_t *) 0x05,
+			(uint8_t *) 0x81,
+			(uint8_t *) 0x0a,
+			(uint8_t *) 0x0b,
+			(uint8_t *) 0x0c,
+		},
+		{
+			(uint8_t *) 0x06,
+			(uint8_t *) 0x07,
+			(uint8_t *) 0x82,
+			(uint8_t *) 0x0a,
+			(uint8_t *) 0x0b,
+			(uint8_t *) 0x0c,
+		},
+		
+		/* The second chip 16-bit */
+		{
+			(uint8_t *) 0xc0,
+			(uint8_t *) 0xc2,
+			(uint8_t *) 0x8f,
+			(uint8_t *) 0xd4,
+			(uint8_t *) 0xd6,
+			(uint8_t *) 0xd8,
+		},
+		{
+			(uint8_t *) 0xc4,
+			(uint8_t *) 0xc6,
+			(uint8_t *) 0x8b,
+			(uint8_t *) 0xd4,
+			(uint8_t *) 0xd6,
+			(uint8_t *) 0xd8,
+		},
+		{
+			(uint8_t *) 0xc8,
+			(uint8_t *) 0xca,
+			(uint8_t *) 0x89,
+			(uint8_t *) 0xd4,
+			(uint8_t *) 0xd6,
+			(uint8_t *) 0xd8,
+		},
+		{
+			(uint8_t *) 0xcc,
+			(uint8_t *) 0xce,
+			(uint8_t *) 0x8a,
+			(uint8_t *) 0xd4,
+			(uint8_t *) 0xd6,
+			(uint8_t *) 0xd8,
+		},
+	},
+	
+	.page_table = NULL,
+	.first = NULL,
+	.second = NULL,
+	.initialized = false,
+};
+
+/* Initialize I/O access to DMA controller I/O ports.
+ *
+ * @param controller DMA Controller structure to initialize.
+ *
+ * @return Error code.
+ *
+ */
+static inline int dma_controller_init(dma_controller_t *controller)
+{
+	assert(controller);
+	int ret = pio_enable(DMA_CONTROLLER_PAGE_BASE, sizeof(dma_page_regs_t),
+	    (void **) &controller->page_table);
+	if (ret != EOK)
+		return EIO;
+	
+	ret = pio_enable(DMA_CONTROLLER_FIRST_BASE,
+	    sizeof(dma_controller_regs_first_t), (void **) &controller->first);
+	if (ret != EOK)
+		return EIO;
+	
+	ret = pio_enable(DMA_CONTROLLER_SECOND_BASE,
+		sizeof(dma_controller_regs_second_t), (void **) &controller->second);
+	if (ret != EOK)
+		return EIO;
+	
+	controller->initialized = true;
+	
+	/* Reset the controller */
+	pio_write_8(&controller->second->master_reset, 0xff);
+	pio_write_8(&controller->first->master_reset, 0xff);
+	
+	return 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 < 16 MB
+ *                for 16 bit and < 1 MB for 8 bit transfers.
+ * @param size    DMA buffer size, limited to 64 KB.
+ * @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 dma_setup_channel(unsigned int channel, uint32_t pa, uint16_t size,
+    uint8_t mode)
+{
+	if ((channel == 0) || (channel == 4))
+		return ENOTSUP;
+	
+	if (channel > 7)
+		return ENOENT;
+	
+	/* DMA is limited to 24bit addresses. */
+	if (pa >= (1 << 24))
+		return EINVAL;
+	
+	/* 8 bit channels use only 4 bits from the page register. */
+	if ((channel > 0) && (channel < 4) && (pa >= (1 << 20)))
+		return EINVAL;
+	
+	fibril_mutex_lock(&guard);
+	
+	if (!controller_8237.initialized)
+		dma_controller_init(&controller_8237);
+	
+	if (!controller_8237.initialized) {
+		fibril_mutex_unlock(&guard);
+		return EIO;
+	}
+	
+	/* 16 bit transfers are a bit special */
+	ddf_msg(LVL_DEBUG, "Unspoiled address: %p and size: %zu.", pa, size);
+	if (channel > 4) {
+		/* Size must be aligned to 16 bits */
+		if ((size & 1) != 0) {
+			fibril_mutex_unlock(&guard);
+			return EINVAL;
+		}
+		
+		size >>= 1;
+		
+		/* Address is fun: lower 16 bits need to be shifted by 1 */
+		pa = ((pa & 0xffff) >> 1) | (pa & 0xff0000);
+	}
+	
+	const dma_channel_t dma_channel = controller_8237.channels[channel];
+	
+	ddf_msg(LVL_DEBUG, "Setting channel %u, to address %p(%zu), mode %hhx.",
+	    channel, pa, size, mode);
+	
+	/* Mask DMA request */
+	uint8_t value = DMA_SINGLE_MASK_CHAN_TO_REG(channel) |
+	    DMA_SINGLE_MASK_MASKED_FLAG;
+	pio_write_8(dma_channel.single_mask_address, value);
+	
+	/* Set mode */
+	value = DMA_MODE_CHAN_TO_REG(channel) | mode;
+	ddf_msg(LVL_DEBUG2, "Writing mode byte: %p:%hhx.",
+	    dma_channel.mode_address, value);
+	pio_write_8(dma_channel.mode_address, value);
+	
+	/* Set address - reset flip-flop */
+	pio_write_8(dma_channel.flip_flop_address, 0);
+	
+	/* Low byte */
+	value = pa & 0xff;
+	ddf_msg(LVL_DEBUG2, "Writing address low byte: %p:%hhx.",
+	    dma_channel.offset_reg_address, value);
+	pio_write_8(dma_channel.offset_reg_address, value);
+	
+	/* High byte */
+	value = (pa >> 8) & 0xff;
+	ddf_msg(LVL_DEBUG2, "Writing address high byte: %p:%hhx.",
+	    dma_channel.offset_reg_address, value);
+	pio_write_8(dma_channel.offset_reg_address, value);
+	
+	/* Page address - third byte */
+	value = (pa >> 16) & 0xff;
+	ddf_msg(LVL_DEBUG2, "Writing address page byte: %p:%hhx.",
+	    dma_channel.page_reg_address, value);
+	pio_write_8(dma_channel.page_reg_address, value);
+	
+	/* Set size - reset flip-flop */
+	pio_write_8(dma_channel.flip_flop_address, 0);
+	
+	/* Low byte */
+	value = (size - 1) & 0xff;
+	ddf_msg(LVL_DEBUG2, "Writing size low byte: %p:%hhx.",
+	    dma_channel.size_reg_address, value);
+	pio_write_8(dma_channel.size_reg_address, value);
+	
+	/* High byte */
+	value = ((size - 1) >> 8) & 0xff;
+	ddf_msg(LVL_DEBUG2, "Writing size high byte: %p:%hhx.",
+	    dma_channel.size_reg_address, value);
+	pio_write_8(dma_channel.size_reg_address, value);
+	
+	/* Unmask DMA request */
+	value = DMA_SINGLE_MASK_CHAN_TO_REG(channel);
+	pio_write_8(dma_channel.single_mask_address, value);
+	
+	fibril_mutex_unlock(&guard);
+	
+	return EOK;
+}
+
+/**
+ * @}
+ */
Index: uspace/drv/bus/isa/i8237.h
===================================================================
--- uspace/drv/bus/isa/i8237.h	(revision fe5e9629448f7d1befa73d7c974f8cedf7bfcbcd)
+++ uspace/drv/bus/isa/i8237.h	(revision fe5e9629448f7d1befa73d7c974f8cedf7bfcbcd)
@@ -0,0 +1,46 @@
+/*
+ * 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 isa
+ * @{
+ */
+
+/** @file
+ * @brief DMA memory management
+ */
+
+#ifndef DRV_BUS_ISA_I8237_H
+#define DRV_BUS_ISA_I8237_H
+
+extern int dma_setup_channel(unsigned int, uint32_t, uint16_t, uint8_t);
+
+#endif
+
+/**
+ * @}
+ */
Index: uspace/drv/bus/isa/isa.c
===================================================================
--- uspace/drv/bus/isa/isa.c	(revision fbcdeb887f643e4a875e51120a2ddbf6fe35e4b3)
+++ uspace/drv/bus/isa/isa.c	(revision fe5e9629448f7d1befa73d7c974f8cedf7bfcbcd)
@@ -2,4 +2,5 @@
  * Copyright (c) 2010 Lenka Trochtova
  * Copyright (c) 2011 Jiri Svoboda
+ * Copyright (c) 2011 Jan Vesely
  * All rights reserved.
  *
@@ -52,4 +53,8 @@
 #include <fcntl.h>
 #include <sys/stat.h>
+#include <ipc/irc.h>
+#include <ipc/services.h>
+#include <sysinfo.h>
+#include <ns.h>
 
 #include <ddf/driver.h>
@@ -61,4 +66,6 @@
 #include <device/hw_res.h>
 
+#include "i8237.h"
+
 #define NAME "isa"
 #define CHILD_FUN_CONF_PATH "/drv/isa/isa.dev"
@@ -70,5 +77,5 @@
 #define ISA_FUN(fun) ((isa_fun_t *) ((fun)->driver_data))
 
-#define ISA_MAX_HW_RES 4
+#define ISA_MAX_HW_RES 5
 
 typedef struct {
@@ -96,12 +103,70 @@
 static bool isa_enable_fun_interrupt(ddf_fun_t *fnode)
 {
-	/* TODO */
-
-	return false;
+	/* This is an old ugly way, copied from pci driver */
+	assert(fnode);
+	isa_fun_t *isa_fun = fnode->driver_data;
+
+	sysarg_t apic;
+	sysarg_t i8259;
+	
+	async_sess_t *irc_sess = NULL;
+	
+	if (((sysinfo_get_value("apic", &apic) == EOK) && (apic))
+	    || ((sysinfo_get_value("i8259", &i8259) == EOK) && (i8259))) {
+		irc_sess = service_connect_blocking(EXCHANGE_SERIALIZE,
+		    SERVICE_IRC, 0, 0);
+	}
+	
+	if (!irc_sess)
+		return false;
+	
+	assert(isa_fun);
+	const hw_resource_list_t *res = &isa_fun->hw_resources;
+	assert(res);
+	for (size_t i = 0; i < res->count; ++i) {
+		if (res->resources[i].type == INTERRUPT) {
+			const int irq = res->resources[i].res.interrupt.irq;
+			
+			async_exch_t *exch = async_exchange_begin(irc_sess);
+			const int rc =
+			    async_req_1_0(exch, IRC_ENABLE_INTERRUPT, irq);
+			async_exchange_end(exch);
+			
+			if (rc != EOK) {
+				async_hangup(irc_sess);
+				return false;
+			}
+		}
+	}
+	
+	async_hangup(irc_sess);
+	return true;
+}
+
+static int isa_dma_channel_fun_setup(ddf_fun_t *fnode,
+    unsigned int channel, uint32_t pa, uint16_t size, uint8_t mode)
+{
+	assert(fnode);
+	isa_fun_t *isa_fun = fnode->driver_data;
+	const hw_resource_list_t *res = &isa_fun->hw_resources;
+	assert(res);
+	
+	const unsigned int ch = channel;
+	for (size_t i = 0; i < res->count; ++i) {
+		if (((res->resources[i].type == DMA_CHANNEL_16) &&
+		    (res->resources[i].res.dma_channel.dma16 == ch)) ||
+		    ((res->resources[i].type == DMA_CHANNEL_8) &&
+		    (res->resources[i].res.dma_channel.dma8 == ch))) {
+			return dma_setup_channel(channel, pa, size, mode);
+		}
+	}
+	
+	return EINVAL;
 }
 
 static hw_res_ops_t isa_fun_hw_res_ops = {
-	&isa_get_fun_resources,
-	&isa_enable_fun_interrupt
+	.get_resource_list = isa_get_fun_resources,
+	.enable_interrupt = isa_enable_fun_interrupt,
+	.dma_channel_setup = isa_dma_channel_fun_setup,
 };
 
@@ -274,4 +339,37 @@
 }
 
+static void isa_fun_set_dma(isa_fun_t *fun, int dma)
+{
+	size_t count = fun->hw_resources.count;
+	hw_resource_t *resources = fun->hw_resources.resources;
+	
+	if (count < ISA_MAX_HW_RES) {
+		if ((dma > 0) && (dma < 4)) {
+			resources[count].type = DMA_CHANNEL_8;
+			resources[count].res.dma_channel.dma8 = dma;
+			
+			fun->hw_resources.count++;
+			ddf_msg(LVL_NOTE, "Added dma 0x%x to function %s", dma,
+			    fun->fnode->name);
+			
+			return;
+		}
+
+		if ((dma > 4) && (dma < 8)) {
+			resources[count].type = DMA_CHANNEL_16;
+			resources[count].res.dma_channel.dma16 = dma;
+			
+			fun->hw_resources.count++;
+			ddf_msg(LVL_NOTE, "Added dma 0x%x to function %s", dma,
+			    fun->fnode->name);
+			
+			return;
+		}
+		
+		ddf_msg(LVL_WARN, "Skipped dma 0x%x for function %s", dma,
+		    fun->fnode->name);
+	}
+}
+
 static void isa_fun_set_io_range(isa_fun_t *fun, size_t addr, size_t len)
 {
@@ -303,4 +401,16 @@
 	if (val != end)
 		isa_fun_set_irq(fun, irq);
+}
+
+static void fun_parse_dma(isa_fun_t *fun, char *val)
+{
+	unsigned int dma = 0;
+	char *end = NULL;
+	
+	val = skip_spaces(val);
+	dma = (unsigned int) strtol(val, &end, 10);
+	
+	if (val != end)
+		isa_fun_set_dma(fun, dma);
 }
 
@@ -396,4 +506,5 @@
 	if (!prop_parse(fun, line, "io_range", &fun_parse_io_range) &&
 	    !prop_parse(fun, line, "irq", &fun_parse_irq) &&
+	    !prop_parse(fun, line, "dma", &fun_parse_dma) &&
 	    !prop_parse(fun, line, "match", &fun_parse_match_id)) {
 
@@ -406,5 +517,5 @@
 {
 	fun->hw_resources.resources =
-	    (hw_resource_t *)malloc(sizeof(hw_resource_t) * ISA_MAX_HW_RES);
+	    (hw_resource_t *) malloc(sizeof(hw_resource_t) * ISA_MAX_HW_RES);
 }
 
@@ -590,5 +701,5 @@
 
 
-static void isa_init() 
+static void isa_init()
 {
 	ddf_log_init(NAME, LVL_ERROR);
Index: uspace/drv/bus/isa/isa.dev
===================================================================
--- uspace/drv/bus/isa/isa.dev	(revision fbcdeb887f643e4a875e51120a2ddbf6fe35e4b3)
+++ uspace/drv/bus/isa/isa.dev	(revision fe5e9629448f7d1befa73d7c974f8cedf7bfcbcd)
@@ -18,2 +18,10 @@
 	irq 5
 	io_range 300 20
+
+sb16:
+	match 100 isa/sb16
+	io_range 220 20
+	io_range 330 2
+	irq 5
+	dma 1
+	dma 5
Index: uspace/drv/bus/pci/pciintel/pci.c
===================================================================
--- uspace/drv/bus/pci/pciintel/pci.c	(revision fbcdeb887f643e4a875e51120a2ddbf6fe35e4b3)
+++ uspace/drv/bus/pci/pciintel/pci.c	(revision fe5e9629448f7d1befa73d7c974f8cedf7bfcbcd)
@@ -187,6 +187,6 @@
 
 static hw_res_ops_t pciintel_hw_res_ops = {
-	&pciintel_get_resources,
-	&pciintel_enable_interrupt
+	.get_resource_list = &pciintel_get_resources,
+	.enable_interrupt = &pciintel_enable_interrupt,
 };
 
