Index: uspace/srv/dd/Makefile
===================================================================
--- uspace/srv/dd/Makefile	(revision 04cb68f2d06da3440e206ec4339c4d23afa3910a)
+++ uspace/srv/dd/Makefile	(revision 04cb68f2d06da3440e206ec4339c4d23afa3910a)
@@ -0,0 +1,42 @@
+#
+# Copyright (c) 2005 Martin Decky
+# Copyright (c) 2007 Jakub Jermar
+# 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 = dd
+
+SOURCES = \
+	main.c \
+	pic.c \
+	pci.c \
+	intel_piix3.c \
+	isa.c \
+	serial.c \
+	intel_method1.c
+
+include $(USPACE_PREFIX)/Makefile.common
Index: uspace/srv/dd/intel_method1.c
===================================================================
--- uspace/srv/dd/intel_method1.c	(revision 04cb68f2d06da3440e206ec4339c4d23afa3910a)
+++ uspace/srv/dd/intel_method1.c	(revision 04cb68f2d06da3440e206ec4339c4d23afa3910a)
@@ -0,0 +1,95 @@
+#include <ddi.h>
+#include <libarch/ddi.h>
+#include <futex.h>
+
+#include "pci.h"
+#include "pci_bus.h"
+#include "pci_conf.h"
+
+#define CONF_ADDR_PORT 0xCF8
+#define CONF_DATA_PORT 0xCFC
+#define CONF_PORT_SIZE 4
+
+static void *conf_addr_port = NULL;
+static void *conf_data_port = NULL;
+
+static atomic_t pci_conf_futex = FUTEX_INITIALIZER;
+
+static void method1_conf_read(pci_dev_t *d, int reg, uint8_t *buf, int len);
+
+#define CONF_ADDR(bus, dev, fn, reg)   ((1 << 31) | (bus << 16) | (dev << 11) | (fn << 8) | (reg & ~3))
+
+uint8_t pci_conf_read_8(pci_dev_t *dev, int reg)
+{
+	uint8_t res;
+	method1_conf_read(dev, reg, &res, 1);
+	return res;
+}
+
+uint16_t pci_conf_read_16(pci_dev_t *dev, int reg)
+{
+	uint16_t res;
+	method1_conf_read(dev, reg, (uint8_t *)&res, 2);
+	return res;
+}
+
+uint32_t pci_conf_read_32(pci_dev_t *dev, int reg)
+{
+	uint32_t res;
+	method1_conf_read(dev, reg, (uint8_t *)&res, 4);
+	return res;	
+}
+
+static void method1_conf_read(pci_dev_t *dev, int reg, uint8_t *buf, int len)
+{
+	futex_down(&pci_conf_futex);
+	uint32_t conf_addr =  CONF_ADDR(dev->bus->num, dev->dev, dev->fn, reg);
+	void *addr = conf_data_port + (reg & 3);
+	
+	pio_write_32(conf_addr_port, conf_addr);
+	
+	switch (len) {
+		case 1:
+			buf[0] = pio_read_8(addr);
+			break;
+		case 2:
+			((uint16_t *)buf)[0] = pio_read_16(addr);
+			break;
+		case 4:
+			((uint32_t *)buf)[0] = pio_read_32(addr);
+			break;
+	}
+	
+	futex_up(&pci_conf_futex);
+}
+
+int pci_bus_init() 
+{	
+	int error;
+	if (error = pio_enable((void *)CONF_ADDR_PORT, CONF_PORT_SIZE, &conf_addr_port)) {
+		printf("PCI: failed to enable configuration address port (error %d)\n", error);
+		return 0;
+	}
+	
+	if (error = pio_enable((void *)CONF_DATA_PORT, CONF_PORT_SIZE, &conf_data_port)) {
+		printf("PCI: failed to enable configuration data port (error %d)\n", error);
+		return 0;
+	}
+	
+	pci_bus_t *bus = pci_alloc_bus();
+	bus->data = NULL;
+	bus->num = 0;
+	pci_bus_register(bus);
+	pci_bus_scan(bus);
+	return 1;
+}
+
+void pci_bus_clean()
+{
+}
+
+/* pci bus structure initialization */
+void pci_init_bus_data(pci_bus_t *bus, pci_bus_t *parent)
+{
+	bus->data = NULL;
+}
Index: uspace/srv/dd/intel_piix3.c
===================================================================
--- uspace/srv/dd/intel_piix3.c	(revision 04cb68f2d06da3440e206ec4339c4d23afa3910a)
+++ uspace/srv/dd/intel_piix3.c	(revision 04cb68f2d06da3440e206ec4339c4d23afa3910a)
@@ -0,0 +1,54 @@
+#include "pci.h"
+#include "intel_piix3.h"
+#include "isa.h"
+
+#define NAME "Intel PIIX3"
+
+
+static int piix3_add_device(pci_dev_t *dev);
+static void * piix3_absolutize(void *phys_addr);
+
+static pci_drv_ops_t piix3_pci_ops = {
+	.add_device = piix3_add_device
+};
+
+static pci_drv_t piix3_drv = {
+	.name = NAME,
+	.link = { NULL, NULL },
+	.vendor_id = 0x8086,
+	.device_id = 0x7010, 
+	.ops = &piix3_pci_ops
+};
+
+static bridge_to_isa_ops_t piix3_bridge_ops = {
+	.absolutize = piix3_absolutize
+};
+
+int intel_piix3_init()
+{
+	pci_driver_register(&piix3_drv);
+	return 0;
+}
+
+
+static int piix3_add_device(pci_dev_t *dev)
+{
+	printf(NAME " driver: new device %3d : %2d : %2d was added.\n", dev->bus->num, dev->dev, dev->fn);
+	
+	// register this device as a pci-to-isa bridge by the isa bus driver
+	bridge_to_isa_t *bridge_dev = isa_alloc_bridge();
+	isa_init_bridge(bridge_dev, &piix3_bridge_ops, dev);
+	isa_register_bridge(bridge_dev);		
+	
+	return 1;
+}
+
+// this might be more usable at different architectures
+static void * piix3_absolutize(void *phys_addr)
+{
+	return phys_addr;
+}
+
+
+
+
Index: uspace/srv/dd/intel_piix3.h
===================================================================
--- uspace/srv/dd/intel_piix3.h	(revision 04cb68f2d06da3440e206ec4339c4d23afa3910a)
+++ uspace/srv/dd/intel_piix3.h	(revision 04cb68f2d06da3440e206ec4339c4d23afa3910a)
@@ -0,0 +1,8 @@
+#ifndef INTEL_PIIX3
+#define INTEL_PIIX3
+
+int intel_piix3_init();
+
+
+
+#endif
Index: uspace/srv/dd/isa.c
===================================================================
--- uspace/srv/dd/isa.c	(revision 04cb68f2d06da3440e206ec4339c4d23afa3910a)
+++ uspace/srv/dd/isa.c	(revision 04cb68f2d06da3440e206ec4339c4d23afa3910a)
@@ -0,0 +1,79 @@
+#include <futex.h>
+#include <assert.h>
+
+#include "isa.h"
+
+LIST_INITIALIZE(isa_bridges_list);
+LIST_INITIALIZE(isa_drivers_list);
+
+static atomic_t isa_bus_futex = FUTEX_INITIALIZER;
+
+static void isa_probe_all(bridge_to_isa_t *bridge);
+static void isa_drv_probe(isa_drv_t *drv);
+
+int isa_bus_init()
+{
+	return 1;
+}
+
+void isa_register_bridge(bridge_to_isa_t *bridge)
+{
+	futex_down(&isa_bus_futex);
+	
+	printf("ISA: registering new sth-to-isa bridge.\n");
+	
+	// add bridge to the list 
+	list_append(&(bridge->link), &isa_bridges_list);
+	
+	// call probe function of all registered  drivers of isa devices
+	isa_probe_all(bridge);
+	
+	futex_up(&isa_bus_futex);
+}
+
+void isa_register_driver(isa_drv_t *drv)
+{
+	assert(drv->name != NULL);
+	
+	futex_down(&isa_bus_futex);
+	
+	printf("ISA: registering new driver '%s'.\n", drv->name);
+	
+	// add bridge to the list 
+	list_append(&(drv->link), &isa_drivers_list);
+	
+	// call driver's probe function on all registered bridges
+	isa_drv_probe(drv);
+	
+	futex_up(&isa_bus_futex);
+}
+
+static void isa_probe_all(bridge_to_isa_t *bridge)
+{
+	link_t *item = isa_drivers_list.next;
+	isa_drv_t *drv = NULL; 
+	
+	while (item != &isa_drivers_list) {
+		drv = list_get_instance(item, isa_drv_t, link);
+		if (drv->ops != NULL && drv->ops->probe != NULL) {
+			drv->ops->probe(bridge);
+		}
+		item = item->next;
+	}
+}
+
+static void isa_drv_probe(isa_drv_t *drv)
+{
+	link_t *item = isa_bridges_list.next;
+	bridge_to_isa_t *bridge = NULL; 
+	
+	if (drv->ops != NULL && drv->ops->probe != NULL) {
+		while (item != &isa_bridges_list) {
+			bridge = list_get_instance(item, bridge_to_isa_t, link);
+			{
+				drv->ops->probe(bridge);
+			}
+			item = item->next;
+		}
+	}	
+}
Index: uspace/srv/dd/isa.h
===================================================================
--- uspace/srv/dd/isa.h	(revision 04cb68f2d06da3440e206ec4339c4d23afa3910a)
+++ uspace/srv/dd/isa.h	(revision 04cb68f2d06da3440e206ec4339c4d23afa3910a)
@@ -0,0 +1,60 @@
+#ifndef ISA_H
+#define ISA_H
+
+#include <adt/list.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+int isa_bus_init();
+
+struct bridge_to_isa;
+struct bridge_to_isa_ops;
+struct isa_drv_ops;
+struct isa_drv;
+
+typedef struct bridge_to_isa bridge_to_isa_t;
+typedef struct bridge_to_isa_ops bridge_to_isa_ops_t;
+typedef struct isa_drv_ops isa_drv_ops_t;
+typedef struct isa_drv isa_drv_t;
+
+
+struct isa_drv_ops {
+	void (*probe)(bridge_to_isa_t *parent);
+};
+
+struct isa_drv {
+	const char *name;
+	link_t link;
+	isa_drv_ops_t *ops; 	
+};
+
+struct bridge_to_isa {
+	link_t link;
+	void *data;
+	bridge_to_isa_ops_t *ops;	
+};
+
+struct bridge_to_isa_ops {
+	void * (*absolutize)(void *phys_addr);	
+};
+
+static inline bridge_to_isa_t * isa_alloc_bridge()
+{
+	bridge_to_isa_t *bridge = (bridge_to_isa_t *)malloc(sizeof(bridge_to_isa_t));
+	link_initialize(&bridge->link);
+	bridge->data = NULL;
+	bridge->ops = NULL;	
+	return bridge;
+}
+
+static inline void isa_init_bridge(bridge_to_isa_t *bridge, bridge_to_isa_ops_t *ops, void *data)
+{
+	bridge->data = data;
+	bridge->ops = ops;	
+}
+
+void isa_register_bridge(bridge_to_isa_t *bridge);
+void isa_register_driver(isa_drv_t *drv);
+
+#endif
Index: uspace/srv/dd/main.c
===================================================================
--- uspace/srv/dd/main.c	(revision 04cb68f2d06da3440e206ec4339c4d23afa3910a)
+++ uspace/srv/dd/main.c	(revision 04cb68f2d06da3440e206ec4339c4d23afa3910a)
@@ -0,0 +1,43 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <async.h>
+
+#include "intel_piix3.h"
+#include "pic.h"
+#include "pci.h"
+#include "pci_bus.h"
+#include "isa.h"
+#include "serial.h"
+
+
+
+int main(int argc, char **argv) 
+{
+	printf("PCI bus driver\n");
+	
+	if (!pic_init()) {
+		printf("PIC initialization failed.\n");
+		return 1;
+	}
+	
+	if (!pci_bus_init()) {
+		printf("PCI bus initialization failed.\n");
+		return 1;
+	}
+	
+	if (!isa_bus_init()) {
+		printf("ISA bus initialization failed.\n");
+		return 1;
+	}	
+	
+	// pci-to-isa bridge device
+	intel_piix3_init();
+	
+	// serial port driver
+	serial_init();
+	
+	printf("PCI + ISA + serial: Accepting connections\n");
+    async_manager();
+	
+	return 0;
+}
Index: uspace/srv/dd/pci.c
===================================================================
--- uspace/srv/dd/pci.c	(revision 04cb68f2d06da3440e206ec4339c4d23afa3910a)
+++ uspace/srv/dd/pci.c	(revision 04cb68f2d06da3440e206ec4339c4d23afa3910a)
@@ -0,0 +1,168 @@
+#include <futex.h>
+#include <assert.h>
+
+#include "pci.h"
+#include "pci_bus.h"
+#include "pci_regs.h"
+#include "pci_conf.h"
+
+#define NAME "PCI"
+
+LIST_INITIALIZE(devices_list);
+LIST_INITIALIZE(buses_list);
+LIST_INITIALIZE(drivers_list);
+
+static atomic_t pci_bus_futex = FUTEX_INITIALIZER;
+
+static int pci_match(pci_drv_t *drv, pci_dev_t *dev);
+static int pci_pass_dev(pci_drv_t *drv, pci_dev_t *dev);
+static void pci_lookup_driver(pci_dev_t *dev);
+static void pci_lookup_devices(pci_drv_t *drv);
+
+
+void pci_bus_scan(pci_bus_t *bus)
+{
+	pci_dev_t *dev = pci_alloc_dev();
+	pci_bus_t *child_bus = NULL;
+	int dnum, fnum, bus_num;
+	bool multi;
+	uint8_t header_type;
+	
+	for (dnum = 0; dnum < 32; dnum++) {
+		multi = true;
+		for (fnum = 0; multi && fnum < 8; fnum++) {
+			pci_init_dev(dev, bus, dnum, fnum);
+			dev->vendor_id = pci_conf_read_16(dev, PCI_VENDOR_ID);
+			dev->device_id = pci_conf_read_16(dev, PCI_DEVICE_ID);
+			if (dev->vendor_id == 0xFFFF) { // device is not present, go on scanning the bus
+				if (fnum == 0) {
+					break;
+				} else {
+					continue;  
+				}
+			}
+			header_type = pci_conf_read_8(dev, PCI_HEADER_TYPE);
+			if (fnum == 0) {
+				 multi = header_type >> 7;  // is the device multifunction?
+			}
+			header_type = header_type & 0x7F; // clear the multifunction bit
+			
+			printf(NAME ": adding new device %3d : %2d : %2d", dev->bus->num, dnum, fnum);
+			printf(" - vendor = 0x%04X, device = 0x%04X.\n", dev->vendor_id, dev->device_id);
+			pci_device_register(dev);			
+			
+			if (header_type == PCI_HEADER_TYPE_BRIDGE || header_type == PCI_HEADER_TYPE_CARDBUS ) {
+				bus_num = pci_conf_read_8(dev, PCI_BRIDGE_SEC_BUS_NUM);
+				printf(NAME ": device is pci-to-pci bridge, secondary bus number = %d.\n", bus_num);
+				if(bus_num > bus->num) {					
+					child_bus = pci_alloc_bus();
+					pci_init_bus(child_bus, bus, bus_num);
+					pci_bus_register(child_bus);
+					pci_bus_scan(child_bus);	
+				}					
+			}
+			
+			dev = pci_alloc_dev();  // alloc new aux. dev. structure
+		}
+	}
+	
+	if (dev->vendor_id == 0xFFFF) {
+		pci_free_dev(dev);  // free the auxiliary device structure
+	}	
+}
+
+/*
+ * Usage: pci_bus_futex must be down.
+ */ 
+static int pci_pass_dev(pci_drv_t *drv, pci_dev_t *dev)
+{
+	assert(dev->driver == NULL);
+	assert(drv->name != NULL);
+	
+	printf(NAME ": passing device to driver '%s'.\n", drv->name);
+	if (drv->ops->add_device != NULL && drv->ops->add_device(dev)) {
+		dev->driver = drv;
+		return 1;
+	}
+	
+	return 0;
+}
+
+/*
+ * Usage: pci_bus_futex must be down.
+ */ 
+static void pci_lookup_driver(pci_dev_t *dev)
+{
+	link_t *item = drivers_list.next;
+	pci_drv_t *drv = NULL; 
+	
+	while (item != &drivers_list) {
+		drv = list_get_instance(item, pci_drv_t, link);
+		if (pci_match(drv, dev) && pci_pass_dev(drv, dev)) {
+			return;
+		}
+		item = item->next;
+	}
+}
+
+/*
+ * Usage: pci_bus_futex must be down.
+ */ 
+static void pci_lookup_devices(pci_drv_t *drv)
+{
+	link_t *item = devices_list.next;
+	pci_dev_t *dev = NULL; 
+	
+	printf(NAME ": looking up devices for a newly added driver '%s'.\n", drv->name);
+	
+	while (item != &devices_list) {
+		dev = list_get_instance(item, pci_dev_t, link);
+		if (dev->driver == NULL && pci_match(drv, dev)) {
+			pci_pass_dev(drv, dev);
+		}
+		item = item->next;
+	}
+}
+
+static int pci_match(pci_drv_t *drv, pci_dev_t *dev)
+{
+	return drv->vendor_id == dev->vendor_id && drv->device_id == dev->device_id;
+}
+
+void pci_bus_register(pci_bus_t *bus)
+{
+	futex_down(&pci_bus_futex);
+	
+	// add the device to the list of pci devices
+	list_append(&(bus->link), &buses_list);
+	
+	futex_up(&pci_bus_futex);
+}
+
+void pci_device_register(pci_dev_t *dev)
+{
+	futex_down(&pci_bus_futex);
+	
+	// add the device to the list of pci devices
+	list_append(&(dev->link), &devices_list);
+	
+	// try to find suitable driver for the device and pass the device to it
+	pci_lookup_driver(dev);
+	
+	futex_up(&pci_bus_futex);	
+}
+
+void pci_driver_register(pci_drv_t *drv)
+{	
+	assert(drv->name != NULL);
+	
+	futex_down(&pci_bus_futex);
+	printf(NAME ": registering new driver '%s'.\n", drv->name);
+	list_append(&(drv->link), &drivers_list);
+	
+	// try to find compatible devices
+	pci_lookup_devices(drv);
+	
+	futex_up(&pci_bus_futex);
+}
+
Index: uspace/srv/dd/pci.h
===================================================================
--- uspace/srv/dd/pci.h	(revision 04cb68f2d06da3440e206ec4339c4d23afa3910a)
+++ uspace/srv/dd/pci.h	(revision 04cb68f2d06da3440e206ec4339c4d23afa3910a)
@@ -0,0 +1,99 @@
+#ifndef PCI_H
+#define PCI_H
+
+#include <adt/list.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+struct pci_drv;
+struct pci_dev;
+struct pci_bus;
+struct pci_drv_ops;
+
+typedef struct pci_drv pci_drv_t;
+typedef struct pci_dev pci_dev_t;
+typedef struct pci_bus pci_bus_t;
+typedef struct pci_drv_ops pci_drv_ops_t;
+
+struct pci_drv {
+	const char *name;
+	link_t link;
+	int vendor_id;
+	int device_id;	
+	pci_drv_ops_t *ops;	
+};
+
+struct pci_dev{
+	link_t link;
+	pci_bus_t *bus;
+	int dev;
+	int fn;
+	
+	int vendor_id;
+	int device_id;
+	pci_drv_t *driver;	
+};
+
+struct pci_drv_ops {
+	int (*add_device)(pci_dev_t *dev);
+	
+};
+
+struct pci_bus {
+	link_t link;
+	int num;
+	// architecture-specific usage
+	void *data;	
+};
+
+void pci_bus_register(pci_bus_t *bus);
+void pci_device_register(pci_dev_t *dev);
+void pci_driver_register(pci_drv_t *drv);
+
+void pci_bus_scan(pci_bus_t *bus);
+
+static inline pci_bus_t* pci_alloc_bus()
+{
+	pci_bus_t *bus = (pci_bus_t *)malloc(sizeof(pci_bus_t));
+	link_initialize(&bus->link);
+	bus->num = 0;
+	bus->data = NULL;
+	return bus;
+}
+
+// arch. spec. initialization of pci bus structure - of its data member
+void pci_init_bus_data(pci_bus_t *bus, pci_bus_t *parent);
+
+static inline void pci_init_bus(pci_bus_t *bus, pci_bus_t *parent, int bus_num)
+{
+	bus->num = bus_num; 
+	pci_init_bus_data(bus, parent);
+}
+
+static inline void pci_free_bus(pci_bus_t *bus)
+{
+	free(bus);
+}
+
+static inline pci_dev_t* pci_alloc_dev()
+{
+	pci_dev_t *dev = (pci_dev_t *)malloc(sizeof(pci_dev_t));
+	bzero(dev, sizeof(pci_dev_t));
+	link_initialize(&dev->link);	
+	return dev;
+}
+
+static inline void pci_init_dev(pci_dev_t *dev, pci_bus_t *bus, int devnum, int fn)
+{
+	dev->bus = bus;
+	dev->dev = devnum;
+	dev->fn = fn;
+}
+
+static inline void pci_free_dev(pci_dev_t *dev)
+{
+	free(dev);
+}
+
+#endif
Index: uspace/srv/dd/pci_bus.h
===================================================================
--- uspace/srv/dd/pci_bus.h	(revision 04cb68f2d06da3440e206ec4339c4d23afa3910a)
+++ uspace/srv/dd/pci_bus.h	(revision 04cb68f2d06da3440e206ec4339c4d23afa3910a)
@@ -0,0 +1,7 @@
+#ifndef PCI_BUS_H
+#define PCI_BUS_H
+
+int pci_bus_init();
+void pci_bus_clean();
+
+#endif
Index: uspace/srv/dd/pci_conf.h
===================================================================
--- uspace/srv/dd/pci_conf.h	(revision 04cb68f2d06da3440e206ec4339c4d23afa3910a)
+++ uspace/srv/dd/pci_conf.h	(revision 04cb68f2d06da3440e206ec4339c4d23afa3910a)
@@ -0,0 +1,10 @@
+#ifndef PCI_CONF_H
+#define PCI_CONF_H
+
+#include "pci.h"
+
+uint8_t pci_conf_read_8(pci_dev_t *dev, int reg);
+uint16_t pci_conf_read_16(pci_dev_t *dev, int reg);
+uint32_t pci_conf_read_32(pci_dev_t *dev, int reg);
+
+#endif
Index: uspace/srv/dd/pci_regs.h
===================================================================
--- uspace/srv/dd/pci_regs.h	(revision 04cb68f2d06da3440e206ec4339c4d23afa3910a)
+++ uspace/srv/dd/pci_regs.h	(revision 04cb68f2d06da3440e206ec4339c4d23afa3910a)
@@ -0,0 +1,78 @@
+#ifndef PCI_REGS_H
+#define PCI_REGS_H
+
+// Header types 
+#define PCI_HEADER_TYPE_DEV			0
+#define PCI_HEADER_TYPE_BRIDGE		1
+#define PCI_HEADER_TYPE_CARDBUS		2
+
+// Header type 0 and 1
+#define PCI_VENDOR_ID		 			0x00
+#define PCI_DEVICE_ID 					0x02
+#define PCI_COMMAND 					0x04
+#define PCI_STATUS 						0x06
+#define PCI_REVISION_ID 				0x08
+#define PCI_PROG_IF						0x09
+#define PCI_SUB_CLASS					0x0A
+#define PCI_BASE_CLASS					0x0B
+#define PCI_CACHE_LINE_SIZE				0x0C
+#define PCI_LATENCY_TIMER				0x0D
+#define PCI_HEADER_TYPE					0x0E
+#define PCI_BIST						0x0F
+
+#define PCI_BASE_ADDR_0 				0x10
+#define PCI_BASE_ADDR_1 				0x14
+
+// Header type 0
+#define PCI_BASE_ADDR_2 				0x18
+#define PCI_BASE_ADDR_3 				0x1B
+#define PCI_BASE_ADDR_4 				0x20
+#define PCI_BASE_ADDR_5 				0x24
+
+#define PCI_CARDBUS_CIS_PTR				0x28
+#define PCI_SUBSYSTEM_VENDOR_ID			0x2C
+#define PCI_SUBSYSTEM_ID				0x2E
+#define PCI_EXP_ROM_BASE				0x30
+#define PCI_CAP_PTR						0x34
+#define PCI_INT_LINE					0x3C
+#define PCI_INT_PIN						0x3D
+#define PCI_MIN_GNT						0x3E
+#define PCI_MAX_LAT						0x3F
+
+// Header type 1
+#define PCI_BRIDGE_PRIM_BUS_NUM 		0x18
+#define PCI_BRIDGE_SEC_BUS_NUM 			0x19
+#define PCI_BRIDGE_SUBORD_BUS_NUM 		0x1A
+#define PCI_BRIDGE_SEC_LATENCY_TIMER 	0x1B
+#define PCI_BRIDGE_IO_BASE 				0x1C
+#define PCI_BRIDGE_IO_LIMIT 			0x1D
+#define PCI_BRIDGE_SEC_STATUS 			0x1E
+#define PCI_BRIDGE_MEMORY_BASE			0x20
+#define PCI_BRIDGE_MEMORY_LIMIT			0x22
+#define PCI_BRIDGE_PREF_MEMORY_BASE		0x24
+#define PCI_BRIDGE_PREF_MEMORY_LIMIT	0x26
+#define PCI_BRIDGE_PREF_MEMORY_BASE_UP	0x28
+#define PCI_BRIDGE_PREF_MEMORY_LIMIT_UP	0x2C
+#define PCI_BRIDGE_IO_BASE_UP			0x30
+#define PCI_BRIDGE_IO_LIMIT_UP 			0x32
+#define PCI_BRIDGE_EXP_ROM_BASE			0x38
+#define PCI_BRIDGE_INT_LINE				0x3C
+#define PCI_BRIDGE_INT_PIN				0x3D
+#define PCI_BRIDGE_CTL					0x3E
+
+
+
+
+
+
+/*  // from psycho spec.
+Reserved             0x28-0x2F n/a
+Expansion ROM        0x30      4 bytes
+Reserved             0x34-0x3B n/a
+Interrupt Line       0x3C      1 byte
+Interrupt Pin        0x3D      1 byte
+MIN_GNT              0x3E      1 byte
+MAX_LAT              0x3F      1 byte*/
+
+
+#endif
Index: uspace/srv/dd/pic.c
===================================================================
--- uspace/srv/dd/pic.c	(revision 04cb68f2d06da3440e206ec4339c4d23afa3910a)
+++ uspace/srv/dd/pic.c	(revision 04cb68f2d06da3440e206ec4339c4d23afa3910a)
@@ -0,0 +1,67 @@
+#include <unistd.h>
+#include <ddi.h>
+#include <libarch/ddi.h>
+#include <stdio.h>
+
+#include "pic.h"
+
+#define PIC1		0x20		/* IO base address for master PIC */
+#define PIC2		0xA0		/* IO base address for slave PIC */
+#define REG_COUNT	2			/* command and data */
+
+#define NAME "PIC"
+
+static ioport8_t *pic1_cmd, *pic1_data, *pic2_cmd, *pic2_data;
+
+static int pic_enable_ports(void *base_phys_addr, ioport8_t **pic_cmd, ioport8_t **pic_data);
+
+
+int pic_init()
+{	
+	printf(NAME ": enabling ports 0x%x - 0x%x.\n", PIC1, PIC1 + 1);
+	if (!pic_enable_ports((void *)PIC1, &pic1_cmd, &pic1_data)) {
+		printf(NAME ": Error - master PIC initialization failed.\n");
+		return 0;
+	}
+	
+	printf(NAME ": enabling ports 0x%x - 0x%x.\n", PIC2, PIC2 + 1);
+	if (!pic_enable_ports((void *)PIC2, &pic2_cmd, &pic2_data)) {
+		printf(NAME ": Error - slave PIC initialization failed.");
+		return 0;
+	}
+	
+	printf(NAME ": initialization was successful.\n");
+	return 1;
+}
+
+static int pic_enable_ports(void *base_phys_addr, ioport8_t **pic_cmd, ioport8_t **pic_data)
+{
+	if (pio_enable(base_phys_addr, REG_COUNT, (void **)(pic_cmd))) {  // Gain control over port's registers.
+		printf(NAME ": Error - cannot gain the port %lx.\n", base_phys_addr);
+		return 0;
+	}
+	
+	*pic_data = *pic_cmd + 1;
+	return 1;
+}
+
+void pic_enable_interrupt(int irq)
+{
+	printf(NAME ": pic_enable_interrupt %d.", irq);
+	pic_enable_irqs(1 << irq);
+	printf(NAME ": interrupt %d enabled.", irq);
+}
+
+void pic_enable_irqs(uint16_t irqmask)
+{
+	uint8_t x;
+
+	if (irqmask & 0xff) {
+		x = pio_read_8(pic1_data);
+		pio_write_8(pic1_data, (uint8_t) (x & (~(irqmask & 0xff))));
+	}
+	if (irqmask >> 8) {
+		x = pio_read_8(pic2_data);
+		pio_write_8(pic2_data, (uint8_t) (x & (~(irqmask >> 8))));
+	}
+}
Index: uspace/srv/dd/pic.h
===================================================================
--- uspace/srv/dd/pic.h	(revision 04cb68f2d06da3440e206ec4339c4d23afa3910a)
+++ uspace/srv/dd/pic.h	(revision 04cb68f2d06da3440e206ec4339c4d23afa3910a)
@@ -0,0 +1,10 @@
+#ifndef PIC_H
+#define PIC_H
+
+#include <stdlib.h>
+
+int pic_init();
+void pic_enable_interrupt(int irq);
+void pic_enable_irqs(uint16_t irqmask);
+
+#endif
Index: uspace/srv/dd/psycho.c
===================================================================
--- uspace/srv/dd/psycho.c	(revision 04cb68f2d06da3440e206ec4339c4d23afa3910a)
+++ uspace/srv/dd/psycho.c	(revision 04cb68f2d06da3440e206ec4339c4d23afa3910a)
@@ -0,0 +1,171 @@
+#include <malloc.h>
+#include <assert.h>
+#include <unistd.h>
+#include <ddi.h>
+#include <libarch/ddi.h>
+#include <stdio.h>
+#include <futex.h>
+
+#include "pci.h"
+#include "pci_bus.h"
+
+#define PCI_CONF_OFFSET   0x001000000
+#define PCI_CONF_SIZE     0x001000000
+
+/* 
+ * virtual address of specified PCI configuration register:
+ * conf_base ... base address of configuration address space 
+ * bus ... bus number 
+ * dev ... device number (0 - 31)
+ * fn  ... function number (0 - 7)
+ * reg ... register number (register's position within PCI configuration header) 
+ **/
+#define CONF_ADDR(conf_base, bus, dev, fn, reg)   ((void *)(conf_base + ((bus << 16) | (dev << 11) | (fn << 8) | reg)))
+
+static atomic_t pci_conf_futex = FUTEX_INITIALIZER;
+
+static long u2p_space_cnt = 0;
+static long *u2p_bases;
+/* virtual addresses of PCI configuration spaces */
+static void **conf_bases;  
+
+static int psycho_init();
+static void u2p_bases_init();
+static void psycho_scan();
+static void * psycho_conf_addr(pci_dev_t *dev, int reg);
+static void psycho_conf_read(pci_dev_t *d, int reg, uint8_t *buf, int len);
+static void psycho_conf_write(pci_dev_t *d, int reg, uint8_t *buf, int len);
+
+
+static void * psycho_conf_addr(pci_dev_t *dev, int reg)
+{	
+	return CONF_ADDR(dev->bus->data, dev->bus->num, dev->dev, dev->fn, reg);
+}
+
+static void psycho_scan()
+{	
+	printf("PCI: psycho_scan\n");
+	int i, num;
+	for (i = 0; i < u2p_space_cnt; i++) {
+		for (num = 0; num <= 0x80; num += 0x80) {		
+			pci_bus_t *bus = pci_alloc_bus();
+			bus->num = num;
+			bus->data = conf_bases[i];
+			pci_bus_register(bus);
+			pci_bus_scan(bus);
+		}
+	}
+}
+
+static int psycho_init()
+{
+	printf("PCI: starting psycho initialization.\n");
+	u2p_bases_init();
+	conf_bases = (void **)malloc(u2p_space_cnt * sizeof(void *));	
+	int i, error;
+	for (i = 0; i < u2p_space_cnt; i++) {
+		if (error = pio_enable((void *)(u2p_bases[i] + PCI_CONF_OFFSET), PCI_CONF_SIZE, &(conf_bases[i]))) {
+			printf("PCI: failed to enable psycho conf. adr. space num. %d. (error %d)\n", i, error);
+			return 0;
+		}
+	}	
+	return 1;
+}
+
+static void u2p_bases_init()
+{
+	// TODO: write this more generally - get this information from firmware (using kernel + sysinfo)	
+	u2p_space_cnt = 2;
+	//u2p_space_cnt = 1;
+	u2p_bases = (void **)malloc(u2p_space_cnt * sizeof(void *));
+	u2p_bases[0] = 0x1c800000000;
+	u2p_bases[1] = 0x1ca00000000;	
+}
+
+uint8_t pci_conf_read_8(pci_dev_t *dev, int reg)
+{
+	uint8_t res;	
+	psycho_conf_read(dev, reg, &res, sizeof(uint8_t));	
+	return res;
+}
+
+uint16_t pci_conf_read_16(pci_dev_t *dev, int reg)
+{
+	uint16_t res;
+	psycho_conf_read(dev, reg, (uint8_t *)(&res), sizeof(uint16_t));	
+	return res;
+}
+
+uint32_t pci_conf_read_32(pci_dev_t *dev, int reg)
+{
+	uint32_t res;
+	psycho_conf_read(dev, reg, (uint8_t *)(&res), sizeof(uint32_t));		
+	return res;	
+}
+
+static inline uint16_t invert_endianness_16(uint16_t x) 
+{
+	return (x & 0xFF) << 8 | (x >> 8);
+}
+
+static inline uint32_t invert_endianness_32(uint32_t x) 
+{
+	return ((x & 0xFF) << 24) | ((x & 0xFF00) << 8) | ((x & 0xFF0000) >> 8) | (x >> 24);
+}
+
+static void psycho_conf_read(pci_dev_t *d, int reg, uint8_t *buf, int len)
+{	
+	futex_down(&pci_conf_futex);
+	switch (len) {
+		case 1:
+			buf[0] = pio_read_8(psycho_conf_addr(d, reg));
+			break;
+		case 2:
+			*((uint16_t *)buf) = invert_endianness_16(pio_read_16(psycho_conf_addr(d, reg)));
+			break;
+		case 4:
+			*((uint32_t *)buf) = invert_endianness_32(pio_read_32(psycho_conf_addr(d, reg)));
+			break;
+	}
+	futex_up(&pci_conf_futex);
+}
+
+static void psycho_conf_write(pci_dev_t *d, int reg, uint8_t *buf, int len)
+{	
+	futex_down(&pci_conf_futex);
+	switch (len) {
+		case 1:
+			pio_write_8(psycho_conf_addr(d, reg), buf[0]);
+			break;
+		case 2:
+			pio_write_16(psycho_conf_addr(d, reg), invert_endianness_16(*((uint16_t *)buf)));
+			break;
+		case 4:
+			pio_write_32(psycho_conf_addr(d, reg), invert_endianness_32(*((uint32_t *)buf)));
+			break;
+	}
+	futex_up(&pci_conf_futex);
+}
+
+/* pci bus structure initialization */
+void pci_init_bus_data(pci_bus_t *bus, pci_bus_t *parent)
+{
+	if (parent != NULL) {
+		bus->data = parent->data;
+	}
+}
+
+int pci_bus_init() 
+{	
+	if(!psycho_init()) {
+		return 0;
+	}	
+	psycho_scan();	
+	return 1;
+}
+
+void pci_bus_clean()
+{
+	free(u2p_bases);
+	free(conf_bases);
+}
Index: uspace/srv/dd/serial.c
===================================================================
--- uspace/srv/dd/serial.c	(revision 04cb68f2d06da3440e206ec4339c4d23afa3910a)
+++ uspace/srv/dd/serial.c	(revision 04cb68f2d06da3440e206ec4339c4d23afa3910a)
@@ -0,0 +1,524 @@
+#include <unistd.h>
+#include <ddi.h>
+#include <libarch/ddi.h>
+#include <ipc/ipc.h>
+#include <ipc/services.h>
+#include <ipc/serial.h>
+#include <ipc/devmap.h>
+#include <ipc/ns.h>
+#include <bool.h>
+#include <errno.h>
+#include <async.h>
+#include <stdio.h>
+#include <futex.h>
+#include <assert.h>
+#include <adt/list.h>
+#include <string.h>
+
+#include "isa.h"
+#include "serial.h"
+#include "pic.h"
+
+#define NAME "serial"
+
+#define REG_COUNT 7
+
+#define MAX_NAME_LEN 8
+#define BUF_LEN 256  // the length of the input buffer
+
+struct cyclic_buffer {
+	uint8_t buf[BUF_LEN];  // cyclic buffer 
+	int start;
+	int cnt;
+};
+
+typedef struct cyclic_buffer cyclic_buffer_t;
+
+// returns false if the buffer is full
+static bool buf_push_back(cyclic_buffer_t *buf, uint8_t item) 
+{
+	if (buf->cnt >= BUF_LEN) {
+		return false;
+	}
+	
+	int pos = (buf->start + buf->cnt) % BUF_LEN;
+	buf->buf[pos] = item;
+	buf->cnt++;
+	return true;
+}
+
+static bool buf_is_empty(cyclic_buffer_t *buf) 
+{
+	return buf->cnt == 0;
+}
+
+// call it on non empty buffer!
+static uint8_t buf_pop_front(cyclic_buffer_t *buf) 
+{
+	assert(!buf_is_empty(buf));
+	
+	uint8_t res = buf->buf[buf->start];
+	buf->start = (buf->start + 1) % BUF_LEN;	
+	buf->cnt--;
+	return res;
+}
+
+static void buf_clear(cyclic_buffer_t *buf) 
+{
+	buf->cnt = 0;
+}
+
+struct serial_dev {
+	link_t link;
+	char name[MAX_NAME_LEN];
+	int handle; // devmapper device handle
+	int devno; // unique device number; used in irq registration (cannot be handle used instead of it?) 
+	bool client_connected;
+	ioport8_t *port;
+	void *phys_addr;
+	int irq;
+	bridge_to_isa_t *parent;
+	cyclic_buffer_t input_buffer;
+	futex_t futex;
+};
+
+typedef struct serial_dev serial_dev_t;
+
+static irq_cmd_t serial_cmds[] = {
+	{
+		.cmd = CMD_ACCEPT
+	}
+};
+
+static irq_code_t serial_pseudocode = {
+	sizeof(serial_cmds) / sizeof(irq_cmd_t),
+	serial_cmds
+};
+
+static void * serial_phys_addresses[] = { (void *)0x3F8, (void *)0x2F8 };
+static int serial_irqs[] = { 4, 3 }; // TODO - what about if there were more than two serial ports?
+static int serial_phys_addr_cnt = sizeof(serial_phys_addresses)/sizeof(void *);
+static int serial_irq_cnt = sizeof(serial_irqs)/sizeof(int);
+
+// number, which should be assigned to a newly found serial device - increment first, then assign to the device
+static int serial_idx = 0; 
+
+static int serial_driver_phone = -1;
+
+LIST_INITIALIZE(serial_devices_list);
+
+static atomic_t serial_futex = FUTEX_INITIALIZER;
+
+
+static void serial_init_port(ioport8_t *port);
+static void serial_write_8(ioport8_t *port, uint8_t c);
+static bool is_transmit_empty(ioport8_t *port);
+static uint8_t serial_read_8(ioport8_t *port);
+static bool serial_received(ioport8_t *port);
+static void serial_probe(bridge_to_isa_t *parent);
+static ioport8_t * serial_probe_port(void *phys_addr);
+static int serial_device_register(int driver_phone, char *name, int *handle);
+static int serial_driver_register(char *name);
+static void serial_putchar(serial_dev_t *dev, ipc_callid_t rid, ipc_call_t *request);
+static void serial_getchar(serial_dev_t *dev, ipc_callid_t rid);
+static void serial_client_conn(ipc_callid_t iid, ipc_call_t *icall);
+static void serial_irq_handler(ipc_callid_t iid, ipc_call_t *icall);
+static serial_dev_t * serial_devno_to_dev(int devno);
+static serial_dev_t * serial_handle_to_dev(int handle);
+static void serial_enable_interrupt(serial_dev_t *dev);
+
+static isa_drv_ops_t serial_isa_ops = {
+	.probe = serial_probe	
+};
+
+static isa_drv_t serial_isa_drv = {
+	.name = NAME,
+	.ops = &serial_isa_ops	
+};
+
+int serial_init()
+{
+	// register driver by devmapper
+	serial_driver_phone = serial_driver_register(NAME);
+    if (serial_driver_phone < 0) {
+		printf(NAME ": Unable to register driver\n");
+		return 0;
+	}
+	
+	// register irq handler
+	printf(NAME ": Registering interrup notification callback function.\n");
+	async_set_interrupt_received(serial_irq_handler);
+	   
+	// register this driver by generic isa bus driver	
+	isa_register_driver(&serial_isa_drv);
+	return 1;
+}
+
+static bool serial_received(ioport8_t *port) 
+{
+   return (pio_read_8(port + 5) & 1) != 0;
+}
+
+static uint8_t serial_read_8(ioport8_t *port) 
+{
+	return pio_read_8(port);
+}
+
+static bool is_transmit_empty(ioport8_t *port) 
+{
+   return (pio_read_8(port + 5) & 0x20) != 0;
+}
+
+static void serial_write_8(ioport8_t *port, uint8_t c) 
+{
+	while (!is_transmit_empty(port)) 
+		;
+	
+	pio_write_8(port, c);
+}
+
+static void serial_init_port(ioport8_t *port) 
+{	
+	pio_write_8(port + 1, 0x00);    // Disable all interrupts
+	pio_write_8(port + 3, 0x80);    // Enable DLAB (set baud rate divisor)
+	pio_write_8(port + 0, 0x60);    // Set divisor to 96 (lo byte) 1200 baud
+	pio_write_8(port + 1, 0x00);    //                   (hi byte)
+	pio_write_8(port + 3, 0x07);    // 8 bits, no parity, two stop bits
+	pio_write_8(port + 2, 0xC7);    // Enable FIFO, clear them, with 14-byte threshold
+	pio_write_8(port + 4, 0x0B);    // RTS/DSR set (Request to Send and Data Terminal Ready lines enabled), 
+									// Aux Output2 set - needed for interrupts
+	 
+}
+
+static void serial_enable_interrupt(serial_dev_t *dev)
+{
+	futex_down(&(dev->futex));
+	// TODO do not call pic directly, do it more generally
+	pic_enable_interrupt(dev->irq);
+	pio_write_8(dev->port + 1 , 0x01);   // Interrupt when data received
+	pio_write_8(dev->port + 4, 0x0B);
+	futex_up(&(dev->futex));
+}
+
+static serial_dev_t * serial_alloc_dev()
+{
+	serial_dev_t *dev = (serial_dev_t *)malloc(sizeof(serial_dev_t));
+	memset(dev, 0, sizeof(serial_dev_t));
+	return dev;
+}
+
+static void serial_init_dev(serial_dev_t *dev, bridge_to_isa_t *parent, int idx)
+{
+	assert(dev != NULL);
+	
+	memset(dev, 0, sizeof(serial_dev_t));
+	dev->parent = parent;
+	dev->phys_addr = dev->parent->ops->absolutize(serial_phys_addresses[idx % serial_phys_addr_cnt]);
+	dev->irq = serial_irqs[idx % serial_irq_cnt];
+	snprintf(dev->name, MAX_NAME_LEN, "com%d", idx + 1);
+	dev->devno = -1;
+	dev->client_connected = false;
+	futex_initialize(&(dev->futex), 1);
+}
+
+static bool serial_probe_dev(serial_dev_t *dev)
+{
+	assert(dev != NULL);
+	
+	return (dev->port = (ioport8_t *)serial_probe_port(dev->phys_addr)) != NULL;	
+}
+
+static void serial_delete_dev(serial_dev_t *dev) {
+	free(dev);
+}
+
+static void serial_probe(bridge_to_isa_t *parent)
+{
+	printf(NAME " driver: probe()\n");	
+	
+	serial_dev_t *dev = serial_alloc_dev();
+	
+	int i;
+	for (i = 0; i < serial_phys_addr_cnt; i++) {			
+		serial_init_dev(dev, parent, serial_idx);
+		printf(NAME ": probing %s. \n", dev->name);
+		if (serial_probe_dev(dev)) {
+			printf(NAME " driver: initializing %s.\n", dev->name);
+			serial_init_port(dev->port);
+			if (EOK != serial_device_register(serial_driver_phone, dev->name, &(dev->handle))) {
+				printf(NAME ": unable to register device %s\n", dev->name);
+			} else {
+				dev->devno = device_assign_devno();
+				
+				// 3rd argument called method is equal devno,this enables us to identify the device 
+				// which caused the interrupt in the irq notification callback function
+				printf(NAME ": registering irq = %d for %s.\n", dev->irq, dev->name);
+				ipc_register_irq(dev->irq, dev->devno, dev->devno, &serial_pseudocode);  
+				list_append(&(dev->link), &serial_devices_list);
+				printf(NAME ": enabling irq = %d for %s.\n", dev->irq, dev->name);
+				serial_enable_interrupt(dev);
+				dev = serial_alloc_dev();
+			}
+		} else {
+			printf(NAME " driver: %s is not present \n", dev->name);
+		}
+		serial_idx++;
+	}
+	
+	serial_delete_dev(dev);
+}
+
+// returns virtual address of the serial port, if the serial port is present at this physical address, NULL otherwise  
+static ioport8_t * serial_probe_port(void *phys_addr)
+{
+	ioport8_t *port_addr = NULL;
+	
+	if (pio_enable(phys_addr, REG_COUNT, (void **)(&port_addr))) {  // Gain control over port's registers.
+		printf(NAME ": Error - cannot gain the port %lx.\n", phys_addr);
+		return NULL;
+	}
+	
+	uint8_t olddata;
+	
+	olddata = pio_read_8(port_addr + 4);
+	pio_write_8(port_addr + 4, 0x10);
+	if ((pio_read_8(port_addr + 6) & 0xf0)) {
+		return NULL;
+	}
+	
+	pio_write_8(port_addr + 4, 0x1f);
+	if ((pio_read_8(port_addr + 6) & 0xf0) != 0xf0) {
+		return NULL;
+	}
+	pio_write_8(port_addr + 4, olddata);
+	
+	return port_addr;
+}
+
+
+static void serial_putchar(serial_dev_t *dev, ipc_callid_t rid, ipc_call_t *request)
+{
+	int c = IPC_GET_ARG1(*request);
+	futex_down(&(dev->futex));
+	serial_write_8(dev->port, (uint8_t)c);	
+	futex_up(&(dev->futex));
+	ipc_answer_0(rid, EOK);
+}
+
+static void serial_getchar(serial_dev_t *dev, ipc_callid_t rid)
+{
+	uint8_t c;
+	printf(NAME ": trying to read from serial port %s\n", dev->name);
+	while (true) {  // TODO: fix it - the queue of requests to read ?
+		futex_down(&(dev->futex));
+		if (!buf_is_empty(&(dev->input_buffer))) {
+			c = buf_pop_front(&(dev->input_buffer));
+			futex_up(&(dev->futex));
+			break;
+		}
+		//printf(NAME "no data ready, trying to read again after some while.\n", dev->name);
+		futex_up(&(dev->futex));
+		async_usleep(10000);
+	}
+	printf(NAME ": serial_getchar: sending characer %c read from %s to client.\n", c, dev->name);
+	ipc_answer_1(rid, EOK, c);		
+}
+
+static serial_dev_t * serial_handle_to_dev(int handle) 
+{	
+	futex_down(&serial_futex);	
+	
+	link_t *item = serial_devices_list.next;
+	serial_dev_t *dev = NULL; 
+	
+	while (item != &serial_devices_list) {
+		dev = list_get_instance(item, serial_dev_t, link);
+		if (dev->handle == handle) {
+			futex_up(&serial_futex);
+			return dev;
+		}
+		item = item->next;
+	}
+	
+	futex_up(&serial_futex);
+	return NULL;
+}
+
+static serial_dev_t * serial_devno_to_dev(int devno)
+{		
+	futex_down(&serial_futex);	
+	
+	link_t *item = serial_devices_list.next;
+	serial_dev_t *dev = NULL; 
+	
+	while (item != &serial_devices_list) {
+		dev = list_get_instance(item, serial_dev_t, link);
+		if (dev->devno == devno) {
+			futex_up(&serial_futex);
+			return dev;
+		}
+		item = item->next;
+	}
+	
+	futex_up(&serial_futex);
+	return NULL;
+}
+
+
+/** Handle one connection to the driver.
+ *
+ * @param iid		Hash of the request that opened the connection.
+ * @param icall		Call data of the request that opened the connection.
+ */
+static void serial_client_conn(ipc_callid_t iid, ipc_call_t *icall)
+{	
+	/*
+	 * Answer the first IPC_M_CONNECT_ME_TO call and remember the handle of the device to which the client connected.
+	 */
+	int handle = IPC_GET_ARG1(*icall); 
+	serial_dev_t *dev = serial_handle_to_dev(handle);
+	
+	if (dev == NULL) {
+		ipc_answer_0(iid, ENOENT);
+		return;
+	}
+	if (dev->client_connected) {
+		ipc_answer_0(iid, ELIMIT);
+		return;
+	}
+		
+	buf_clear(&(dev->input_buffer));  // synchronization with interrupt service routine ?
+	dev->client_connected = true;
+	ipc_answer_0(iid, EOK);
+	
+	while (1) {
+		ipc_callid_t callid;
+		ipc_call_t call;
+	
+		callid = async_get_call(&call);
+		switch  (IPC_GET_METHOD(call)) {
+		case IPC_M_PHONE_HUNGUP:
+			/*
+			 * The other side has hung up.
+			 * Answer the message and exit the fibril.
+			 */
+			ipc_answer_0(callid, EOK);
+			dev->client_connected = false;
+			return;
+			break;
+		case SERIAL_GETCHAR:
+			serial_getchar(dev, callid);
+			break;
+		case SERIAL_PUTCHAR:
+			serial_putchar(dev, callid, &call);
+			break;
+		default:
+			ipc_answer_0(callid, ENOTSUP);
+			break;
+		}
+	}	
+}
+
+
+/**
+ *  Register the driver with the given name and return its newly created phone.
+ */ 
+static int serial_driver_register(char *name)
+{
+	ipcarg_t retval;
+	aid_t req;
+	ipc_call_t answer;
+	int phone;
+	ipcarg_t callback_phonehash;
+
+	phone = ipc_connect_me_to(PHONE_NS, SERVICE_DEVMAP, DEVMAP_DRIVER, 0);
+
+	while (phone < 0) {
+		usleep(10000);
+		phone = ipc_connect_me_to(PHONE_NS, SERVICE_DEVMAP, DEVMAP_DRIVER, 0);
+	}
+	
+	req = async_send_2(phone, DEVMAP_DRIVER_REGISTER, 0, 0, &answer);
+
+	retval = ipc_data_write_start(phone, (char *) name, str_length(name) + 1); 
+
+	if (retval != EOK) {
+		async_wait_for(req, NULL);
+		return -1;
+	}
+
+	async_set_client_connection(serial_client_conn);  // set callback function which will serve client connections
+
+	ipc_connect_to_me(phone, 0, 0, 0, &callback_phonehash);
+	async_wait_for(req, &retval);
+
+	return phone;
+}
+
+static int serial_device_register(int driver_phone, char *name, int *handle)
+{
+	ipcarg_t retval;
+	aid_t req;
+	ipc_call_t answer;
+	
+	if (handle != NULL) {
+		*handle = -1;
+	}
+
+	req = async_send_2(driver_phone, DEVMAP_DEVICE_REGISTER, 0, 0, &answer);
+
+	retval = ipc_data_write_start(driver_phone, (char *) name, str_length(name) + 1); 
+
+	if (retval != EOK) {
+		async_wait_for(req, NULL);
+		return retval;
+	}
+
+	async_wait_for(req, &retval);
+	
+	if (EOK == retval) {
+		if (NULL != handle)
+			*handle = (int) IPC_GET_ARG1(answer);
+	}
+	
+	return retval;
+}
+
+static void serial_read_from_device(serial_dev_t *dev)
+{	
+	bool cont = true;
+	
+	while (cont) {	
+		futex_down(&(dev->futex));
+		if (cont = serial_received(dev->port)) {
+			uint8_t val = serial_read_8(dev->port);
+			printf(NAME ": character %c read from %s.\n", val, dev->name);
+			if (dev->client_connected) {
+				if (!buf_push_back(&(dev->input_buffer), val)) {
+					printf(NAME ": buffer overflow on %s.\n", dev->name);
+				} else {
+					printf(NAME ": the character %c saved to the buffer of %s.\n", val, dev->name);
+				}
+			} else {
+				printf(NAME ": no client is connected to %s, discarding the character which was read.\n", dev->name);
+			}
+		}
+		futex_up(&(dev->futex));
+		usleep(10000);
+	}	
+}
+
+// TODO - this is the only irq handling function registered by this task.
+// (A task can register only one such function.)
+// If more drivers within the task needed to handle interrupts, 
+// there will have to be one generic handler redistributing
+// irq notification messages among them. 
+// Or the change of ansync framework will be needed.
+static void serial_irq_handler(ipc_callid_t iid, ipc_call_t *icall)
+{
+	printf(NAME ": irq handler\n");
+	int devno = IPC_GET_METHOD(*icall);
+	serial_dev_t *dev = serial_devno_to_dev(devno);
+	serial_read_from_device(dev);	
+}
+
Index: uspace/srv/dd/serial.h
===================================================================
--- uspace/srv/dd/serial.h	(revision 04cb68f2d06da3440e206ec4339c4d23afa3910a)
+++ uspace/srv/dd/serial.h	(revision 04cb68f2d06da3440e206ec4339c4d23afa3910a)
@@ -0,0 +1,8 @@
+#ifndef SERIAL_H
+#define SERIAL_H
+
+int serial_init();
+
+
+#endif
+
Index: uspace/srv/devman/Makefile
===================================================================
--- uspace/srv/devman/Makefile	(revision 04cb68f2d06da3440e206ec4339c4d23afa3910a)
+++ uspace/srv/devman/Makefile	(revision 04cb68f2d06da3440e206ec4339c4d23afa3910a)
@@ -0,0 +1,39 @@
+#
+# Copyright (c) 2005 Martin Decky
+# Copyright (c) 2007 Jakub Jermar
+# 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 = devman
+
+SOURCES = \
+	main.c \
+	devman.c \
+	match.c \
+	util.c
+
+include $(USPACE_PREFIX)/Makefile.common
Index: uspace/srv/devman/devman.c
===================================================================
--- uspace/srv/devman/devman.c	(revision 04cb68f2d06da3440e206ec4339c4d23afa3910a)
+++ uspace/srv/devman/devman.c	(revision 04cb68f2d06da3440e206ec4339c4d23afa3910a)
@@ -0,0 +1,938 @@
+/*
+ * Copyright (c) 2010 Lenka Trochtova
+ * 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 devman
+ * @{
+ */
+
+#include <errno.h>
+#include <fcntl.h>
+#include <sys/stat.h>
+#include <ipc/driver.h>
+#include <ipc/devman.h>
+#include <devmap.h>
+
+#include "devman.h"
+
+// hash table operations
+
+static hash_index_t devices_hash(unsigned long key[])
+{
+	return key[0] % DEVICE_BUCKETS;
+}
+
+static int devman_devices_compare(unsigned long key[], hash_count_t keys, link_t *item)
+{
+	node_t *dev = hash_table_get_instance(item, node_t, devman_link);
+	return (dev->handle == (device_handle_t) key[0]);
+}
+
+static int devmap_devices_compare(unsigned long key[], hash_count_t keys, link_t *item)
+{
+	node_t *dev = hash_table_get_instance(item, node_t, devmap_link);
+	return (dev->devmap_handle == (dev_handle_t) key[0]);
+}
+
+static void devices_remove_callback(link_t *item)
+{
+}
+
+static hash_table_operations_t devman_devices_ops = {
+	.hash = devices_hash,
+	.compare = devman_devices_compare,
+	.remove_callback = devices_remove_callback
+};
+
+static hash_table_operations_t devmap_devices_ops = {
+	.hash = devices_hash,
+	.compare = devmap_devices_compare,
+	.remove_callback = devices_remove_callback
+};
+
+/** Allocate and initialize a new driver structure.
+ * 
+ * @return driver structure.
+ */
+driver_t * create_driver() 
+{	
+	driver_t *res = malloc(sizeof(driver_t));
+	if(res != NULL) {
+		init_driver(res);
+	}
+	return res;
+}
+
+/** Add a driver to the list of drivers.
+ * 
+ * @param drivers_list the list of drivers.
+ * @param drv the driver's structure.
+ */
+void add_driver(driver_list_t *drivers_list, driver_t *drv)
+{
+	fibril_mutex_lock(&drivers_list->drivers_mutex);
+	list_prepend(&drv->drivers, &drivers_list->drivers);
+	fibril_mutex_unlock(&drivers_list->drivers_mutex);
+	
+	printf(NAME": the '%s' driver was added to the list of available drivers.\n", drv->name);
+}
+
+/** Read match id at the specified position of a string and set 
+ * the position in the string to the first character following the id.
+ * 
+ * @param buf the position in the input string.
+ * 
+ * @return the match id. 
+ */
+char * read_match_id(char **buf) 
+{
+	char *res = NULL;
+	size_t len = get_nonspace_len(*buf);
+	if (len > 0) {
+		res = malloc(len + 1);
+		if (res != NULL) {
+			str_ncpy(res, len + 1, *buf, len);	
+			*buf += len;
+		}
+	}
+	return res;
+}
+
+/**
+ * Read match ids and associated match scores from a string.
+ * 
+ * Each match score in the string is followed by its match id. 
+ * The match ids and match scores are separated by whitespaces. 
+ * Neither match ids nor match scores can contain whitespaces. 
+ * 
+ * @param buf the string from which the match ids are read.
+ * @param ids the list of match ids into which the match ids and scores are added.
+ * 
+ * @return true if at least one match id and associated match score was successfully read, false otherwise.
+ */
+bool parse_match_ids(char *buf, match_id_list_t *ids)
+{
+	int score = 0;
+	char *id = NULL;
+	int ids_read = 0;
+	
+	while (true) {
+		// skip spaces
+		if (!skip_spaces(&buf)) {
+			break;
+		}
+		// read score
+		score = strtoul(buf, &buf, 10);
+		
+		// skip spaces
+		if (!skip_spaces(&buf)) {
+			break;
+		}
+		
+		// read id
+		if (NULL == (id = read_match_id(&buf))) {
+			break;			
+		}
+		
+		// create new match_id structure
+		match_id_t *mid = create_match_id();
+		mid->id = id;
+		mid->score = score;
+		
+		/// add it to the list
+		add_match_id(ids, mid);
+		
+		ids_read++;		
+	}	
+	
+	return ids_read > 0;
+}
+
+/**
+ * Read match ids and associated match scores from a file.
+ * 
+ * Each match score in the file is followed by its match id. 
+ * The match ids and match scores are separated by whitespaces. 
+ * Neither match ids nor match scores can contain whitespaces. 
+ * 
+ * @param buf the path to the file from which the match ids are read.
+ * @param ids the list of match ids into which the match ids and scores are added.
+ * 
+ * @return true if at least one match id and associated match score was successfully read, false otherwise.
+ */
+bool read_match_ids(const char *conf_path, match_id_list_t *ids) 
+{	
+	printf(NAME ": read_match_ids conf_path = %s.\n", conf_path);
+	
+	bool suc = false;	
+	char *buf = NULL;
+	bool opened = false;
+	int fd;		
+	size_t len = 0;
+	
+	fd = open(conf_path, O_RDONLY);
+	if (fd < 0) {
+		printf(NAME ": unable to open %s\n", conf_path);
+		goto cleanup;
+	} 
+	opened = true;	
+	
+	len = lseek(fd, 0, SEEK_END);
+	lseek(fd, 0, SEEK_SET);	
+	if (len == 0) {
+		printf(NAME ": configuration file '%s' is empty.\n", conf_path);
+		goto cleanup;		
+	}
+	
+	buf = malloc(len + 1);
+	if (buf == NULL) {
+		printf(NAME ": memory allocation failed when parsing file '%s'.\n", conf_path);
+		goto cleanup;
+	}	
+	
+	if (0 >= read(fd, buf, len)) {
+		printf(NAME ": unable to read file '%s'.\n", conf_path);
+		goto cleanup;
+	}
+	buf[len] = 0;
+	
+	suc = parse_match_ids(buf, ids);
+	
+cleanup:
+	
+	free(buf);
+	
+	if(opened) {
+		close(fd);	
+	}
+	
+	return suc;
+}
+
+/**
+ * Get information about a driver.
+ * 
+ * Each driver has its own directory in the base directory. 
+ * The name of the driver's directory is the same as the name of the driver.
+ * The driver's directory contains driver's binary (named as the driver without extension)
+ * and the configuration file with match ids for device-to-driver matching 
+ * (named as the driver with a special extension).
+ * 
+ * This function searches for the driver's directory and containing configuration files.
+ * If all the files needed are found, they are parsed and 
+ * the information about the driver is stored to the driver's structure.
+ * 
+ * @param base_path the base directory, in which we look for driver's subdirectory.
+ * @param name the name of the driver.
+ * @param drv the driver structure to fill information in.
+ * 
+ * @return true on success, false otherwise.
+ */
+bool get_driver_info(const char *base_path, const char *name, driver_t *drv)
+{
+	printf(NAME ": get_driver_info base_path = %s, name = %s.\n", base_path, name);
+	
+	assert(base_path != NULL && name != NULL && drv != NULL);
+	
+	bool suc = false;
+	char *match_path = NULL;	
+	size_t name_size = 0;
+	
+	// read the list of match ids from the driver's configuration file
+	if (NULL == (match_path = get_abs_path(base_path, name, MATCH_EXT))) {
+		goto cleanup;
+	}	
+	
+	if (!read_match_ids(match_path, &drv->match_ids)) {
+		goto cleanup;
+	}	
+	
+	// allocate and fill driver's name
+	name_size = str_size(name)+1;
+	drv->name = malloc(name_size);
+	if (!drv->name) {
+		goto cleanup;
+	}	
+	str_cpy(drv->name, name_size, name);
+	
+	// initialize path with driver's binary
+	if (NULL == (drv->binary_path = get_abs_path(base_path, name, ""))) {
+		goto cleanup;
+	}
+	
+	// check whether the driver's binary exists
+	struct stat s;
+	if (stat(drv->binary_path, &s) == ENOENT) {
+		printf(NAME ": driver not found at path %s.", drv->binary_path);
+		goto cleanup;
+	}
+	
+	suc = true;
+	
+cleanup:
+	
+	if (!suc) {
+		free(drv->binary_path);
+		free(drv->name);
+		// set the driver structure to the default state
+		init_driver(drv); 
+	}
+	
+	free(match_path);
+	
+	return suc;
+}
+
+/** Lookup drivers in the directory.
+ * 
+ * @param drivers_list the list of available drivers.
+ * @param dir_path the path to the directory where we search for drivers. 
+ * 
+ * @return number of drivers which were found.
+ */ 
+int lookup_available_drivers(driver_list_t *drivers_list, const char *dir_path)
+{
+	printf(NAME ": lookup_available_drivers, dir = %s \n", dir_path);
+	
+	int drv_cnt = 0;
+	DIR *dir = NULL;
+	struct dirent *diren;
+
+	dir = opendir(dir_path);
+	
+	if (dir != NULL) {
+		driver_t *drv = create_driver();
+		while ((diren = readdir(dir))) {			
+			if (get_driver_info(dir_path, diren->d_name, drv)) {
+				add_driver(drivers_list, drv);
+				drv_cnt++;
+				drv = create_driver();
+			}	
+		}
+		delete_driver(drv);
+		closedir(dir);
+	}
+	
+	return drv_cnt;
+}
+
+/** Create root device node in the device tree.
+ * 
+ * @param tree the device tree.
+ * @return true on success, false otherwise.
+ */
+bool create_root_node(dev_tree_t *tree)
+{
+	printf(NAME ": create_root_node\n");
+	node_t *node = create_dev_node();
+	if (node) {		
+		insert_dev_node(tree, node, clone_string(""), NULL);
+		match_id_t *id = create_match_id();
+		id->id = clone_string("root");
+		id->score = 100;
+		add_match_id(&node->match_ids, id);
+		tree->root_node = node;
+	}
+	return node != NULL;	
+}
+
+/** Lookup the best matching driver for the specified device in the list of drivers.
+ * 
+ * A match between a device and a driver is found 
+ * if one of the driver's match ids match one of the device's match ids.
+ * The score of the match is the product of the driver's and device's score associated with the matching id.
+ * The best matching driver for a device is the driver
+ * with the highest score of the match between the device and the driver.
+ * 
+ * @param drivers_list the list of drivers, where we look for the driver suitable for handling the device.
+ * @param node the device node structure of the device.
+ *
+ * @return the best matching driver or NULL if no matching driver is found.
+ */
+driver_t * find_best_match_driver(driver_list_t *drivers_list, node_t *node)
+{
+	//printf(NAME ": find_best_match_driver for device '%s' \n", node->pathname);
+	driver_t *best_drv = NULL, *drv = NULL;
+	int best_score = 0, score = 0;
+	
+	fibril_mutex_lock(&drivers_list->drivers_mutex);
+	
+	link_t *link = drivers_list->drivers.next;		
+	while (link != &drivers_list->drivers) {
+		drv = list_get_instance(link, driver_t, drivers);
+		score = get_match_score(drv, node);
+		if (score > best_score) {
+			best_score = score;
+			best_drv = drv;
+		}	
+		link = link->next;
+	}
+	
+	fibril_mutex_unlock(&drivers_list->drivers_mutex);
+	
+	return best_drv;	
+}
+
+/**
+ * Assign a driver to a device.
+ * 
+ * @param node the device's node in the device tree.
+ * @param drv the driver.
+ */
+void attach_driver(node_t *node, driver_t *drv) 
+{
+	printf(NAME ": attach_driver %s to device %s\n", drv->name, node->pathname);
+	
+	fibril_mutex_lock(&drv->driver_mutex);
+	
+	node->drv = drv;
+	list_append(&node->driver_devices, &drv->devices);
+	
+	fibril_mutex_unlock(&drv->driver_mutex);
+}
+
+/** Start a driver.
+ * 
+ * The driver's mutex is assumed to be locked.
+ * 
+ * @param drv the driver's structure.
+ * @return true if the driver's task is successfully spawned, false otherwise.
+ */
+bool start_driver(driver_t *drv)
+{
+	printf(NAME ": start_driver '%s'\n", drv->name);
+	
+	const char *argv[2];
+	
+	argv[0] = drv->name;
+	argv[1] = NULL;
+	
+	int err;
+	if (!task_spawn(drv->binary_path, argv, &err)) {
+		printf(NAME ": error spawning %s, errno = %d\n", drv->name, err);
+		return false;
+	}
+	
+	drv->state = DRIVER_STARTING;
+	return true;
+}
+
+/** Find device driver in the list of device drivers.
+ * 
+ * @param drv_list the list of device drivers.
+ * @param drv_name the name of the device driver which is searched.
+ * @return the device driver of the specified name, if it is in the list, NULL otherwise.  
+ */
+driver_t * find_driver(driver_list_t *drv_list, const char *drv_name) 
+{	
+	driver_t *res = NULL;
+	
+	fibril_mutex_lock(&drv_list->drivers_mutex);	
+	
+	driver_t *drv = NULL;
+	link_t *link = drv_list->drivers.next; 	
+	while (link !=  &drv_list->drivers) {
+		drv = list_get_instance(link, driver_t, drivers);
+		if (0 == str_cmp(drv->name, drv_name)) {
+			res = drv;
+			break;
+		}		
+		link = link->next;
+	}	
+	
+	fibril_mutex_unlock(&drv_list->drivers_mutex);
+	
+	return res;
+}
+
+/** Remember the driver's phone.
+ * @param driver the driver.
+ * @param phone the phone to the driver.
+ */
+void set_driver_phone(driver_t *driver, ipcarg_t phone)
+{		
+	fibril_mutex_lock(&driver->driver_mutex);	
+	assert(DRIVER_STARTING == driver->state);
+	driver->phone = phone;	
+	fibril_mutex_unlock(&driver->driver_mutex);	
+}
+
+/**
+ * Notify driver about the devices to which it was assigned.
+ * 
+ * The driver's mutex must be locked.
+ * 
+ * @param driver the driver to which the devices are passed.
+ */
+static void pass_devices_to_driver(driver_t *driver, dev_tree_t *tree)
+{	
+	printf(NAME ": pass_devices_to_driver\n");
+	node_t *dev;
+	link_t *link;
+	
+	int phone = ipc_connect_me_to(driver->phone, DRIVER_DEVMAN, 0, 0);
+	
+	if (0 < phone) {
+		
+		link = driver->devices.next;
+		while (link != &driver->devices) {
+			dev = list_get_instance(link, node_t, driver_devices);
+			add_device(phone, driver, dev, tree);
+			link = link->next;
+		}
+		
+		ipc_hangup(phone);
+	}
+}
+
+/** Finish the initialization of a driver after it has succesfully started 
+ * and after it has registered itself by the device manager.
+ * 
+ * Pass devices formerly matched to the driver to the driver and remember the driver is running and fully functional now.
+ * 
+ * @param driver the driver which registered itself as running by the device manager.
+ */
+void initialize_running_driver(driver_t *driver, dev_tree_t *tree) 
+{	
+	printf(NAME ": initialize_running_driver\n");
+	fibril_mutex_lock(&driver->driver_mutex);
+	
+	// pass devices which have been already assigned to the driver to the driver
+	pass_devices_to_driver(driver, tree);	
+	
+	// change driver's state to running
+	driver->state = DRIVER_RUNNING;	
+	
+	fibril_mutex_unlock(&driver->driver_mutex);
+}
+
+
+static void devmap_register_tree_device(node_t *node, dev_tree_t *tree)
+{
+	// create devmap path and name for the device
+	char *devmap_pathname = NULL;
+	char *devmap_name = NULL;
+	
+	asprintf(&devmap_name, "%s", node->pathname);
+	if (NULL == devmap_name) {
+		return;
+	}
+	
+	replace_char(devmap_name, '/', DEVMAP_SEPARATOR);
+	
+	asprintf(&devmap_pathname, "%s/%s", DEVMAP_DEVICE_NAMESPACE, devmap_name);
+	if (NULL == devmap_pathname) {
+		free(devmap_name);
+		return;
+	}	
+	
+	devmap_device_register(devmap_pathname, &node->devmap_handle);
+	
+	tree_add_devmap_device(tree, node);
+	
+	free(devmap_name);
+	free(devmap_pathname);	
+}
+
+
+/** Pass a device to running driver.
+ * 
+ * @param drv the driver's structure.
+ * @param node the device's node in the device tree.
+ */
+void add_device(int phone, driver_t *drv, node_t *node, dev_tree_t *tree)
+{
+	printf(NAME ": add_device\n");
+	
+	ipcarg_t rc;
+	ipc_call_t answer;
+	
+	// send the device to the driver
+	aid_t req = async_send_1(phone, DRIVER_ADD_DEVICE, node->handle, &answer);
+	
+	// send the device's name to the driver
+	rc = async_data_write_start(phone, node->name, str_size(node->name) + 1);
+    if (rc != EOK) {
+		// TODO handle error
+    }
+	
+	// wait for answer from the driver
+	async_wait_for(req, &rc);
+	switch(rc) {
+	case EOK:
+		node->state = DEVICE_USABLE;
+		devmap_register_tree_device(node, tree);
+		break;
+	case ENOENT:
+		node->state = DEVICE_NOT_PRESENT;
+		break;
+	default:
+		node->state = DEVICE_INVALID;		
+	}
+	
+	return;
+}
+
+/** 
+ * Find suitable driver for a device and assign the driver to it.
+ * 
+ * @param node the device node of the device in the device tree.
+ * @param drivers_list the list of available drivers.
+ * 
+ * @return true if the suitable driver is found and successfully assigned to the device, false otherwise. 
+ */
+bool assign_driver(node_t *node, driver_list_t *drivers_list, dev_tree_t *tree) 
+{
+	//printf(NAME ": assign_driver\n");
+	
+	// find the driver which is the most suitable for handling this device
+	driver_t *drv = find_best_match_driver(drivers_list, node);
+	if (NULL == drv) {
+		printf(NAME ": no driver found for device '%s'.\n", node->pathname); 
+		return false;		
+	}
+	
+	// attach the driver to the device
+	attach_driver(node, drv);
+	
+	if (DRIVER_NOT_STARTED == drv->state) {
+		// start driver
+		start_driver(drv);
+	} 
+	
+	if (DRIVER_RUNNING == drv->state) {
+		// notify driver about new device
+		int phone = ipc_connect_me_to(drv->phone, DRIVER_DEVMAN, 0, 0);
+		if (phone > 0) {
+			add_device(phone, drv, node, tree);		
+			ipc_hangup(phone);
+		}
+	}
+	
+	return true;
+}
+
+/**
+ * Initialize the device tree.
+ * 
+ * Create root device node of the tree and assign driver to it.
+ * 
+ * @param tree the device tree.
+ * @param the list of available drivers.
+ * @return true on success, false otherwise.
+ */
+bool init_device_tree(dev_tree_t *tree, driver_list_t *drivers_list)
+{
+	printf(NAME ": init_device_tree.\n");
+	
+	tree->current_handle = 0;
+	
+	hash_table_create(&tree->devman_devices, DEVICE_BUCKETS, 1, &devman_devices_ops);
+	hash_table_create(&tree->devmap_devices, DEVICE_BUCKETS, 1, &devmap_devices_ops);
+	
+	fibril_rwlock_initialize(&tree->rwlock);
+	
+	// create root node and add it to the device tree
+	if (!create_root_node(tree)) {
+		return false;
+	}
+
+	// find suitable driver and start it
+	return assign_driver(tree->root_node, drivers_list, tree);
+}
+
+/** Create and set device's full path in device tree.
+ * 
+ * @param node the device's device node.
+ * @param parent the parent device node.
+ * @return true on success, false otherwise (insufficient resources etc.). 
+ */
+static bool set_dev_path(node_t *node, node_t *parent)
+{	
+	assert(NULL != node->name);
+	
+	size_t pathsize = (str_size(node->name) + 1);	
+	if (NULL != parent) {		
+		pathsize += str_size(parent->pathname) + 1;		
+	}
+	
+	if (NULL == (node->pathname = (char *)malloc(pathsize))) {
+		printf(NAME ": failed to allocate device path.\n");
+		return false;
+	}
+	
+	if (NULL != parent) {
+		str_cpy(node->pathname, pathsize, parent->pathname);
+		str_append(node->pathname, pathsize, "/");
+		str_append(node->pathname, pathsize, node->name);
+	} else {
+		str_cpy(node->pathname, pathsize, node->name);
+	}
+	
+	return true;
+}
+
+/** Insert new device into device tree.
+ * 
+ * The device tree's rwlock should be already held exclusively when calling this function.
+ * 
+ * @param tree the device tree.
+ * @param node the newly added device node. 
+ * @param dev_name the name of the newly added device.
+ * @param parent the parent device node.
+ * @return true on success, false otherwise (insufficient resources etc.).
+ */
+bool insert_dev_node(dev_tree_t *tree, node_t *node, char *dev_name, node_t *parent)
+{
+	// printf(NAME ": insert_dev_node\n");
+	
+	assert(NULL != node && NULL != tree && NULL != dev_name);
+	
+	node->name = dev_name;
+	if (!set_dev_path(node, parent)) {
+		fibril_rwlock_write_unlock(&tree->rwlock);
+		return false;		
+	}
+	
+	// add the node to the handle-to-node map
+	node->handle = ++tree->current_handle;
+	unsigned long key = node->handle;
+	hash_table_insert(&tree->devman_devices, &key, &node->devman_link);
+
+	// add the node to the list of its parent's children
+	node->parent = parent;
+	if (NULL != parent) {
+		list_append(&node->sibling, &parent->children);		
+	}
+	return true;
+}
+
+/** 
+ * Find device node with a specified path in the device tree.
+ * 
+ * @param path the path of the device node in the device tree.
+ * @param tree the device tree.
+ * 
+ * @return the device node if it is present in the tree, NULL otherwise.
+ */
+node_t * find_dev_node_by_path(dev_tree_t *tree, char *path)
+{
+	fibril_rwlock_read_lock(&tree->rwlock);
+	
+	node_t *dev = tree->root_node;
+	// relative path to the device from its parent (but with '/' at the beginning)
+	char *rel_path = path;
+	char *next_path_elem = NULL;
+	bool cont = '/' == rel_path[0];
+	
+	while (cont && NULL != dev) {		
+		next_path_elem  = get_path_elem_end(rel_path + 1);		
+		if ('/' == next_path_elem[0]) {
+			cont = true;
+			next_path_elem[0] = 0;
+		} else {
+			cont = false;
+		}
+		
+		dev = find_node_child(dev, rel_path + 1);		
+		
+		if (cont) {
+			// restore the original path
+			next_path_elem[0] = '/';
+		}
+		rel_path = next_path_elem;		
+	}
+	
+	fibril_rwlock_read_unlock(&tree->rwlock);
+	
+	return dev;
+}
+
+/**
+ * Find child device node with a specified name.
+ * 
+ * Device tree rwlock should be held at least for reading. 
+ * 
+ * @param parent the parent device node.
+ * @param name the name of the child device node.
+ * 
+ * @return the child device node.
+ */
+node_t *find_node_child(node_t *parent, const char *name)
+{
+	node_t *dev;
+	link_t *link;
+			
+	link = parent->children.next;
+	
+	while (link != &parent->children) {
+		dev = list_get_instance(link, node_t, sibling);
+		
+		if (0 == str_cmp(name, dev->name)) {
+			return dev;			
+		}
+		
+		link = link->next;
+	}	
+		
+	return NULL;
+}
+
+/** Create unique device name within the class. 
+ * 
+ * @param cl the class.
+ * @param base_dev_name contains base name for the device 
+ * if it was specified by the driver when it registered the device by the class; 
+ * NULL if driver specified no base name.
+ * @return the unique name for the device within the class.
+ */
+char * create_dev_name_for_class(dev_class_t *cl, const char *base_dev_name)
+{
+	char *dev_name;
+	const char *base_name;
+	if (NULL != base_dev_name) {
+		base_name = base_dev_name;
+	} else {
+		base_name = cl->base_dev_name;
+	}
+	
+	size_t idx = get_new_class_dev_idx(cl);
+	asprintf(&dev_name, "%s%d", base_name, idx);
+	return dev_name;	
+}
+
+/** Add the device to the class.
+ * 
+ * The device may be added to multiple classes and a class may contain multiple devices.
+ * The class and the device are associated with each other by the dev_class_info_t structure.
+ * 
+ * @param dev the device.
+ * @param class the class.
+ * @param base_dev_name the base name of the device within the class if specified by the driver,
+ * NULL otherwise.
+ * @return dev_class_info_t structure which associates the device with the class.
+ */
+dev_class_info_t * add_device_to_class(node_t *dev, dev_class_t *cl, const char *base_dev_name)
+{	
+	dev_class_info_t *info = create_dev_class_info();
+	if (NULL != info) {
+		info->dev_class = cl;
+		info->dev = dev;
+		
+		// add the device to the class
+		fibril_mutex_lock(&cl->mutex);
+		list_append(&info->link, &cl->devices);
+		fibril_mutex_unlock(&cl->mutex);
+		
+		// add the class to the device
+		list_append(&info->dev_classes, &dev->classes);
+		
+		// create unique name for the device within the class
+		info->dev_name = create_dev_name_for_class(cl, base_dev_name);	
+	}
+	
+	return info;
+}
+
+dev_class_t * get_dev_class(class_list_t *class_list, char *class_name)
+{
+	dev_class_t *cl;
+	fibril_rwlock_write_lock(&class_list->rwlock);	
+	cl = find_dev_class_no_lock(class_list, class_name);
+	if (NULL == cl) {
+		cl = create_dev_class();
+		if (NULL != cl) {
+			cl->name = class_name;	
+			cl->base_dev_name = "";
+			add_dev_class_no_lock(class_list, cl);
+		}		
+	}	
+	fibril_rwlock_write_unlock(&class_list->rwlock);
+	return cl;
+}
+
+dev_class_t * find_dev_class_no_lock(class_list_t *class_list, const char *class_name)
+{
+	dev_class_t *cl;
+	link_t *link = class_list->classes.next;
+	while (link != &class_list->classes) {
+		cl = list_get_instance(link, dev_class_t, link);
+		if (0 == str_cmp(cl->name, class_name)) {
+			return cl;
+		}
+	}
+	
+	return NULL;	
+}
+
+void init_class_list(class_list_t *class_list)
+{
+	list_initialize(&class_list->classes);
+	fibril_rwlock_initialize(&class_list->rwlock);
+	hash_table_create(&class_list->devmap_devices, DEVICE_BUCKETS, 1, &devmap_devices_ops);	
+}
+
+
+// devmap devices
+
+node_t *find_devmap_tree_device(dev_tree_t *tree, dev_handle_t devmap_handle)
+{
+	node_t *dev = NULL;
+	link_t *link;
+	unsigned long key = (unsigned long)devmap_handle;
+	
+	fibril_rwlock_read_lock(&tree->rwlock);
+	link = hash_table_find(&tree->devmap_devices, &key);	
+	if (NULL != link) {
+		dev = hash_table_get_instance(link, node_t, devmap_link);
+	}
+	fibril_rwlock_read_unlock(&tree->rwlock);
+	
+	return dev;
+}
+
+node_t *find_devmap_class_device(class_list_t *classes, dev_handle_t devmap_handle)
+{
+	node_t *dev = NULL;
+	dev_class_info_t *cli;
+	link_t *link;
+	unsigned long key = (unsigned long)devmap_handle;
+	
+	fibril_rwlock_read_lock(&classes->rwlock);
+	link = hash_table_find(&classes->devmap_devices, &key);	
+	if (NULL != link) {
+		cli = hash_table_get_instance(link, dev_class_info_t, devmap_link);
+		dev = cli->dev;
+	}
+	fibril_rwlock_read_unlock(&classes->rwlock);
+	
+	return dev;	
+}
+
+
+/** @}
+ */
Index: uspace/srv/devman/devman.h
===================================================================
--- uspace/srv/devman/devman.h	(revision 04cb68f2d06da3440e206ec4339c4d23afa3910a)
+++ uspace/srv/devman/devman.h	(revision 04cb68f2d06da3440e206ec4339c4d23afa3910a)
@@ -0,0 +1,449 @@
+/*
+ * Copyright (c) 2010 Lenka Trochtova
+ * 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 devman
+ * @{
+ */
+
+#ifndef DEVMAN_H_
+#define DEVMAN_H_
+
+#include <assert.h>
+#include <bool.h>
+#include <dirent.h>
+#include <str.h>
+#include <adt/list.h>
+#include <adt/hash_table.h>
+#include <ipc/ipc.h>
+#include <ipc/devman.h>
+#include <ipc/devmap.h>
+#include <fibril_synch.h>
+#include <atomic.h>
+
+#include "util.h"
+
+#define NAME "devman"
+
+#define MATCH_EXT ".ma"
+#define DEVICE_BUCKETS 256
+
+#define DEVMAP_CLASS_NAMESPACE "class"
+#define DEVMAP_DEVICE_NAMESPACE "devices"
+#define DEVMAP_SEPARATOR '\\'
+
+struct node;
+typedef struct node node_t;
+
+typedef enum {
+	/** driver has not been started */
+	DRIVER_NOT_STARTED = 0,
+	/** driver has been started, but has not registered as running and ready to receive requests */
+	DRIVER_STARTING,
+	/** driver is running and prepared to serve incomming requests */
+	DRIVER_RUNNING
+} driver_state_t;
+
+/** Representation of device driver.
+ */
+typedef struct driver {
+	/** Pointers to previous and next drivers in a linked list */
+	link_t drivers;
+	/** Specifies whether the driver has been started and wheter is running and prepared to receive requests.*/
+	int state;
+	/** Phone asociated with this driver */
+	ipcarg_t phone;
+	/** Name of the device driver */
+	char *name;
+	/** Path to the driver's binary */
+	const char *binary_path;
+	/** List of device ids for device-to-driver matching.*/
+	match_id_list_t match_ids;
+	/** Pointer to the linked list of devices controlled by this driver */
+	link_t devices;
+	/** Fibril mutex for this driver - driver state, list of devices, phone.*/
+	fibril_mutex_t driver_mutex;
+} driver_t;
+
+/** The list of drivers. */
+typedef struct driver_list {
+	/** List of drivers */
+	link_t drivers;
+	/** Fibril mutex for list of drivers. */
+	fibril_mutex_t drivers_mutex;	
+} driver_list_t;
+
+/** The state of the device. */
+typedef enum {
+	DEVICE_NOT_INITIALIZED = 0,
+	DEVICE_USABLE,
+	DEVICE_NOT_PRESENT,
+	DEVICE_INVALID
+} device_state_t;
+
+/** Representation of a node in the device tree.*/
+struct node {
+	/** The global unique identifier of the device.*/
+	device_handle_t handle;
+	/** The name of the device specified by its parent. */
+	char *name;
+	/** Full path and name of the device in device hierarchi (i. e. in full path in device tree).*/
+	char *pathname;	
+	/** The node of the parent device. */
+	node_t *parent;
+	/** Pointers to previous and next child devices in the linked list of parent device's node.*/
+	link_t sibling;
+	/** List of child device nodes. */
+	link_t children;
+	/** List of device ids for device-to-driver matching.*/
+	match_id_list_t match_ids;
+	/** Driver of this device.*/
+	driver_t *drv;
+	/** The state of the device. */
+	device_state_t state;
+	/** Pointer to the previous and next device in the list of devices
+	    owned by one driver */
+	link_t driver_devices;
+	/** The list of device classes to which this device belongs.*/
+	link_t classes;
+	/** Devmap handle if the device is registered by devmapper. */
+	dev_handle_t devmap_handle;
+	/** Used by the hash table of devices indexed by devman device handles.*/
+	link_t devman_link;
+	/** Used by the hash table of devices indexed by devmap device handles.*/
+	link_t devmap_link;
+};
+
+
+/** Represents device tree.
+ */
+typedef struct dev_tree {
+	/** Root device node. */
+	node_t *root_node;
+	/** The next available handle - handles are assigned in a sequential manner.*/
+	device_handle_t current_handle;
+	/** Synchronize access to the device tree.*/
+	fibril_rwlock_t rwlock;
+	/** Hash table of all devices indexed by devman handles.*/
+	hash_table_t devman_devices;
+	/** Hash table of devices registered by devmapper, indexed by devmap handles.*/
+	hash_table_t devmap_devices;
+} dev_tree_t;
+
+typedef struct dev_class {	
+	/** The name of the class.*/
+	const char *name;
+	/** Pointer to the previous and next class in the list of registered classes.*/
+	link_t link;	
+	/** List of dev_class_info structures - one for each device registered by this class.*/
+	link_t devices;
+	/** Default base name for the device within the class, might be overrided by the driver.*/	
+	const char *base_dev_name;
+	/** Unique numerical identifier of the newly added device.*/
+	size_t curr_dev_idx;
+	/** Synchronize access to the list of devices in this class. */
+	fibril_mutex_t mutex;
+} dev_class_t;
+
+/** Provides n-to-m mapping between device nodes and classes 
+ * - each device may be register to the arbitrary number of classes 
+ * and each class may contain the arbitrary number of devices. */
+typedef struct dev_class_info {
+	/** The class.*/
+	dev_class_t *dev_class;
+	/** The device.*/
+	node_t *dev;
+	/** Pointer to the previous and next class info in the list of devices registered by the class.*/
+	link_t link;
+	/** Pointer to the previous and next class info in the list of classes by which the device is registered.*/
+	link_t dev_classes;
+	/** The name of the device within the class.*/
+	char *dev_name;	
+	/** The handle of the device by device mapper in the class namespace.*/
+	dev_handle_t devmap_handle;
+	/** Link in the hash table of devices registered by the devmapper using their class names.*/
+	link_t devmap_link;
+} dev_class_info_t;
+
+/** The list of device classes. */
+typedef struct class_list {
+	/** List of classes */
+	link_t classes;
+	/** Hash table of devices registered by devmapper using their class name, indexed by devmap handles.*/
+	hash_table_t devmap_devices;
+	/** Fibril mutex for list of classes. */
+	fibril_rwlock_t rwlock;	
+} class_list_t;
+
+// Match ids and scores
+
+int get_match_score(driver_t *drv, node_t *dev);
+
+bool parse_match_ids(char *buf, match_id_list_t *ids);
+bool read_match_ids(const char *conf_path, match_id_list_t *ids);
+char * read_match_id(char **buf);
+char * read_id(const char **buf);
+
+// Drivers
+
+/** 
+ * Initialize the list of device driver's.
+ * 
+ * @param drv_list the list of device driver's.
+ * 
+ */
+static inline void init_driver_list(driver_list_t *drv_list) 
+{
+	assert(NULL != drv_list);
+	
+	list_initialize(&drv_list->drivers);
+	fibril_mutex_initialize(&drv_list->drivers_mutex);	
+}
+
+driver_t * create_driver(void);
+bool get_driver_info(const char *base_path, const char *name, driver_t *drv);
+int lookup_available_drivers(driver_list_t *drivers_list, const char *dir_path);
+
+driver_t * find_best_match_driver(driver_list_t *drivers_list, node_t *node);
+bool assign_driver(node_t *node, driver_list_t *drivers_list, dev_tree_t *tree);
+
+void add_driver(driver_list_t *drivers_list, driver_t *drv);
+void attach_driver(node_t *node, driver_t *drv);
+void add_device(int phone, driver_t *drv, node_t *node, dev_tree_t *tree);
+bool start_driver(driver_t *drv);
+
+driver_t * find_driver(driver_list_t *drv_list, const char *drv_name);
+void set_driver_phone(driver_t *driver, ipcarg_t phone);
+void initialize_running_driver(driver_t *driver, dev_tree_t *tree);
+
+/** 
+ * Initialize device driver structure.
+ * 
+ * @param drv the device driver structure.
+ * 
+ */
+static inline void init_driver(driver_t *drv)
+{
+	assert(drv != NULL);
+
+	memset(drv, 0, sizeof(driver_t));
+	list_initialize(&drv->match_ids.ids);
+	list_initialize(&drv->devices);
+	fibril_mutex_initialize(&drv->driver_mutex);	
+}
+
+/**
+ * Device driver structure clean-up.
+ * 
+ * @param drv the device driver structure. 
+ */
+static inline void clean_driver(driver_t *drv)
+{
+	assert(drv != NULL);
+
+	free_not_null(drv->name);
+	free_not_null(drv->binary_path); 
+
+	clean_match_ids(&drv->match_ids);
+
+	init_driver(drv);
+}
+
+/**
+ * Delete device driver structure.
+ * 
+ *  @param drv the device driver structure.* 
+ */
+static inline void delete_driver(driver_t *drv)
+{
+	assert(NULL != drv);
+	
+	clean_driver(drv);
+	free(drv);
+}
+
+// Device nodes
+/**
+ * Create a new device node.
+ * 
+ * @return a device node structure.
+ * 
+ */
+static inline node_t * create_dev_node()
+{
+	node_t *res = malloc(sizeof(node_t));
+	
+	if (res != NULL) {
+		memset(res, 0, sizeof(node_t));
+		list_initialize(&res->children);
+		list_initialize(&res->match_ids.ids);
+		list_initialize(&res->classes);
+	}
+	
+	return res;
+}
+
+/**
+ * Delete a device node.
+ * 
+ * @param node a device node structure.
+ * 
+ */
+static inline void delete_dev_node(node_t *node)
+{
+	assert(list_empty(&node->children) && NULL == node->parent && NULL == node->drv);
+	
+	clean_match_ids(&node->match_ids);
+	free_not_null(node->name);
+	free_not_null(node->pathname);
+	free(node);	
+}
+
+/**
+ * Find the device node structure of the device witch has the specified handle.
+ * 
+ * Device tree's rwlock should be held at least for reading.
+ * 
+ * @param tree the device tree where we look for the device node.
+ * @param handle the handle of the device.
+ * @return the device node. 
+ */
+static inline node_t * find_dev_node_no_lock(dev_tree_t *tree, device_handle_t handle)
+{
+	unsigned long key = handle;
+	link_t *link = hash_table_find(&tree->devman_devices, &key);
+	return hash_table_get_instance(link, node_t, devman_link);
+}
+
+/**
+ * Find the device node structure of the device witch has the specified handle.
+ * 
+ * @param tree the device tree where we look for the device node.
+ * @param handle the handle of the device.
+ * @return the device node. 
+ */
+static inline node_t * find_dev_node(dev_tree_t *tree, device_handle_t handle)
+{
+	node_t *node = NULL;
+	
+	fibril_rwlock_read_lock(&tree->rwlock);
+	
+	node = find_dev_node_no_lock(tree, handle);
+	
+	fibril_rwlock_read_unlock(&tree->rwlock);
+	
+	return node;
+}
+
+node_t * find_dev_node_by_path(dev_tree_t *tree, char *path);
+node_t *find_node_child(node_t *parent, const char *name);
+
+// Device tree
+
+bool init_device_tree(dev_tree_t *tree, driver_list_t *drivers_list);
+bool create_root_node(dev_tree_t *tree);
+bool insert_dev_node(dev_tree_t *tree, node_t *node, char *dev_name, node_t *parent);
+
+// Device classes
+
+/** Create device class. 
+ *   
+ * @return device class.
+ */
+static inline dev_class_t * create_dev_class()
+{
+	dev_class_t *cl = (dev_class_t *)malloc(sizeof(dev_class_t));
+	if (NULL != cl) {
+		memset(cl, 0, sizeof(dev_class_t));
+		list_initialize(&cl->devices);
+		fibril_mutex_initialize(&cl->mutex);
+	}
+	return cl;	
+}
+
+/** Create device class info. 
+ * 
+ * @return device class info.
+ */
+static inline dev_class_info_t * create_dev_class_info()
+{
+	dev_class_info_t *info = (dev_class_info_t *)malloc(sizeof(dev_class_info_t));
+	if (NULL != info) {
+		memset(info, 0, sizeof(dev_class_info_t));
+	}
+	return info;	
+}
+
+static inline size_t get_new_class_dev_idx(dev_class_t *cl)
+{
+	size_t dev_idx;
+	fibril_mutex_lock(&cl->mutex);
+	dev_idx = ++cl->curr_dev_idx;
+	fibril_mutex_unlock(&cl->mutex);
+	return dev_idx;
+}
+
+char * create_dev_name_for_class(dev_class_t *cl, const char *base_dev_name);
+dev_class_info_t * add_device_to_class(node_t *dev, dev_class_t *cl, const char *base_dev_name);
+
+void init_class_list(class_list_t *class_list);
+
+dev_class_t * get_dev_class(class_list_t *class_list, char *class_name);
+dev_class_t * find_dev_class_no_lock(class_list_t *class_list, const char *class_name);
+
+static inline void add_dev_class_no_lock(class_list_t *class_list, dev_class_t *cl)
+{
+	list_append(&cl->link, &class_list->classes);
+}
+
+
+// devmap devices
+
+node_t *find_devmap_tree_device(dev_tree_t *tree, dev_handle_t devmap_handle);
+node_t *find_devmap_class_device(class_list_t *classes, dev_handle_t devmap_handle);
+
+
+static inline void class_add_devmap_device(class_list_t *class_list, dev_class_info_t *cli)
+{
+	unsigned long key = (unsigned long)cli->devmap_handle;
+	fibril_rwlock_write_lock(&class_list->rwlock);
+	hash_table_insert(&class_list->devmap_devices, &key, &cli->devmap_link);
+	fibril_rwlock_write_unlock(&class_list->rwlock);
+}
+
+static inline void tree_add_devmap_device(dev_tree_t *tree, node_t *node)
+{
+	unsigned long key = (unsigned long)node->devmap_handle;
+	fibril_rwlock_write_lock(&tree->rwlock);
+	hash_table_insert(&tree->devmap_devices, &key, &node->devmap_link);
+	fibril_rwlock_write_unlock(&tree->rwlock);	
+}
+
+#endif
+
+/** @}
+ */
Index: uspace/srv/devman/main.c
===================================================================
--- uspace/srv/devman/main.c	(revision 04cb68f2d06da3440e206ec4339c4d23afa3910a)
+++ uspace/srv/devman/main.c	(revision 04cb68f2d06da3440e206ec4339c4d23afa3910a)
@@ -0,0 +1,573 @@
+/*
+ * Copyright (c) 2010 Lenka Trochtova
+ * 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 devman Device manager.
+ * @brief HelenOS device manager.
+ * @{
+ */
+
+/** @file
+ */
+
+#include <assert.h>
+#include <ipc/services.h>
+#include <ipc/ns.h>
+#include <async.h>
+#include <stdio.h>
+#include <errno.h>
+#include <bool.h>
+#include <fibril_synch.h>
+#include <stdlib.h>
+#include <str.h>
+#include <dirent.h>
+#include <fcntl.h>
+#include <sys/stat.h>
+#include <ctype.h>
+#include <ipc/devman.h>
+#include <ipc/driver.h>
+#include <thread.h>
+#include <devmap.h>
+
+#include "devman.h"
+
+#define DRIVER_DEFAULT_STORE  "/srv/drivers"
+
+static driver_list_t drivers_list;
+static dev_tree_t device_tree;
+static class_list_t class_list;
+
+/**
+ * Register running driver.
+ */
+static driver_t * devman_driver_register(void)
+{	
+	printf(NAME ": devman_driver_register \n");
+	
+	ipc_call_t icall;
+	ipc_callid_t iid = async_get_call(&icall);
+	driver_t *driver = NULL;
+	
+	if (IPC_GET_METHOD(icall) != DEVMAN_DRIVER_REGISTER) {
+		ipc_answer_0(iid, EREFUSED);
+		return NULL;
+	}
+	
+	char *drv_name = NULL;
+	
+	// Get driver name
+	int rc = async_data_write_accept((void **)&drv_name, true, 0, 0, 0, 0);
+	if (rc != EOK) {
+		ipc_answer_0(iid, rc);
+		return NULL;
+	}
+	printf(NAME ": the %s driver is trying to register by the service.\n", drv_name);
+	
+	// Find driver structure
+	driver = find_driver(&drivers_list, drv_name);
+	
+	if (NULL == driver) {
+		printf(NAME ": no driver named %s was found.\n", drv_name);
+		free(drv_name);
+		drv_name = NULL;
+		ipc_answer_0(iid, ENOENT);
+		return NULL;
+	}
+	
+	free(drv_name);
+	drv_name = NULL;
+	
+	// Create connection to the driver
+	printf(NAME ":  creating connection to the %s driver.\n", driver->name);	
+	ipc_call_t call;
+	ipc_callid_t callid = async_get_call(&call);		
+	if (IPC_GET_METHOD(call) != IPC_M_CONNECT_TO_ME) {
+		ipc_answer_0(callid, ENOTSUP);
+		ipc_answer_0(iid, ENOTSUP);
+		return NULL;
+	}
+	
+	// remember driver's phone
+	set_driver_phone(driver, IPC_GET_ARG5(call));
+	
+	printf(NAME ":  the %s driver was successfully registered as running.\n", driver->name);
+	
+	ipc_answer_0(callid, EOK);	
+	
+	ipc_answer_0(iid, EOK);
+	
+	return driver;
+}
+
+/**
+ * Receive device match ID from the device's parent driver and add it to the list of devices match ids.
+ * 
+ * @param match_ids the list of the device's match ids.
+ * 
+ * @return 0 on success, negative error code otherwise. 
+ */
+static int devman_receive_match_id(match_id_list_t *match_ids) {
+	
+	match_id_t *match_id = create_match_id();
+	ipc_callid_t callid;
+	ipc_call_t call;
+	int rc = 0;
+	
+	callid = async_get_call(&call);
+	if (DEVMAN_ADD_MATCH_ID != IPC_GET_METHOD(call)) {
+		printf(NAME ": ERROR: devman_receive_match_id - invalid protocol.\n");
+		ipc_answer_0(callid, EINVAL); 
+		delete_match_id(match_id);
+		return EINVAL;
+	}
+	
+	if (NULL == match_id) {
+		printf(NAME ": ERROR: devman_receive_match_id - failed to allocate match id.\n");
+		ipc_answer_0(callid, ENOMEM);
+		return ENOMEM;
+	}
+	
+	ipc_answer_0(callid, EOK);
+	
+	match_id->score = IPC_GET_ARG1(call);
+	
+	char *match_id_str;
+	rc = async_data_write_accept((void **)&match_id_str, true, 0, 0, 0, 0);
+	match_id->id = match_id_str;
+	if (EOK != rc) {
+		delete_match_id(match_id);
+		printf(NAME ": devman_receive_match_id - failed to receive match id string.\n");
+		return rc;
+	}
+	
+	list_append(&match_id->link, &match_ids->ids);
+	
+	printf(NAME ": received match id '%s', score = %d \n", match_id->id, match_id->score);
+	return rc;
+}
+
+/**
+ * Receive device match IDs from the device's parent driver 
+ * and add them to the list of devices match ids.
+ * 
+ * @param match_count the number of device's match ids to be received.
+ * @param match_ids the list of the device's match ids.
+ * 
+ * @return 0 on success, negative error code otherwise.
+ */
+static int devman_receive_match_ids(ipcarg_t match_count, match_id_list_t *match_ids) 
+{	
+	int ret = EOK;
+	size_t i;
+	for (i = 0; i < match_count; i++) {
+		if (EOK != (ret = devman_receive_match_id(match_ids))) {
+			return ret;
+		}
+	}
+	return ret;
+}
+
+/** Handle child device registration. 
+ * 
+ * Child devices are registered by their parent's device driver.
+ */
+static void devman_add_child(ipc_callid_t callid, ipc_call_t *call)
+{
+	//printf(NAME ": devman_add_child\n");
+	
+	device_handle_t parent_handle = IPC_GET_ARG1(*call);
+	ipcarg_t match_count = IPC_GET_ARG2(*call);
+	dev_tree_t *tree = &device_tree;
+	
+	fibril_rwlock_write_lock(&tree->rwlock);
+	node_t *parent =  find_dev_node_no_lock(&device_tree, parent_handle);
+	
+	if (NULL == parent) {
+		fibril_rwlock_write_unlock(&tree->rwlock);
+		ipc_answer_0(callid, ENOENT);
+		return;
+	}	
+	
+	char *dev_name = NULL;
+	int rc = async_data_write_accept((void **)&dev_name, true, 0, 0, 0, 0);	
+	if (EOK != rc) {
+		fibril_rwlock_write_unlock(&tree->rwlock);
+		ipc_answer_0(callid, rc);
+		return;
+	}
+	//printf(NAME ": newly added child device's name is '%s'.\n", dev_name);
+	
+	node_t *node = create_dev_node();
+	if (!insert_dev_node(&device_tree, node, dev_name, parent)) {
+		fibril_rwlock_write_unlock(&tree->rwlock);
+		delete_dev_node(node);
+		ipc_answer_0(callid, ENOMEM);
+		return;
+	}	
+	fibril_rwlock_write_unlock(&tree->rwlock);
+	
+	printf(NAME ": devman_add_child %s\n", node->pathname);
+	
+	devman_receive_match_ids(match_count, &node->match_ids);
+	
+	// return device handle to parent's driver
+	ipc_answer_1(callid, EOK, node->handle);
+	
+	// try to find suitable driver and assign it to the device
+	assign_driver(node, &drivers_list, &device_tree);	
+}
+
+static void devmap_register_class_dev(dev_class_info_t *cli)
+{
+	// create devmap path and name for the device
+	char *devmap_pathname = NULL;
+	asprintf(&devmap_pathname, "%s/%s%c%s", DEVMAP_CLASS_NAMESPACE, cli->dev_class->name, DEVMAP_SEPARATOR, cli->dev_name);
+	if (NULL == devmap_pathname) {
+		return;
+	}
+	
+	// register the device by the device mapper and remember its devmap handle
+	devmap_device_register(devmap_pathname, &cli->devmap_handle);	
+	
+	// add device to the hash map of class devices registered by device mapper
+	class_add_devmap_device(&class_list, cli);
+	
+	free(devmap_pathname);	
+}
+
+static void devman_add_device_to_class(ipc_callid_t callid, ipc_call_t *call)
+{
+	device_handle_t handle = IPC_GET_ARG1(*call);
+	
+	// Get class name
+	char *class_name;
+	int rc = async_data_write_accept((void **)&class_name, true, 0, 0, 0, 0);
+	if (rc != EOK) {
+		ipc_answer_0(callid, rc);
+		return;
+	}	
+	
+	node_t *dev = find_dev_node(&device_tree, handle);
+	if (NULL == dev) {
+		ipc_answer_0(callid, ENOENT);
+		return;
+	}
+	
+	dev_class_t *cl = get_dev_class(&class_list, class_name);
+		
+	dev_class_info_t *class_info = add_device_to_class(dev, cl, NULL);
+	
+	// register the device's class alias by devmapper
+	devmap_register_class_dev(class_info);
+	
+	printf(NAME ": device '%s' added to class '%s', class name '%s' was asigned to it\n", dev->pathname, class_name, class_info->dev_name);
+	
+	ipc_answer_0(callid, EOK);	
+}
+
+/**
+ * Initialize driver which has registered itself as running and ready.
+ * 
+ * The initialization is done in a separate fibril to avoid deadlocks 
+ * (if the driver needed to be served by devman during the driver's initialization). 
+ */
+static int init_running_drv(void *drv)
+{
+	driver_t *driver = (driver_t *)drv;
+	initialize_running_driver(driver, &device_tree);	
+	printf(NAME ": the %s driver was successfully initialized. \n", driver->name);
+	return 0;
+}
+
+/** Function for handling connections from a driver to the device manager.
+ */
+static void devman_connection_driver(ipc_callid_t iid, ipc_call_t *icall)
+{	
+	/* Accept the connection */
+	ipc_answer_0(iid, EOK);
+	
+	driver_t *driver = devman_driver_register();
+	if (NULL == driver)
+		return;
+	
+	// Initialize the driver as running (e.g. pass assigned devices to it) in a separate fibril;
+	// the separate fibril is used to enable the driver 
+	// to use devman service during the driver's initialization.
+	fid_t fid = fibril_create(init_running_drv, driver);
+	if (fid == 0) {
+		printf(NAME ": Error creating fibril for the initialization of the newly registered running driver.\n");
+		return;
+	}
+	fibril_add_ready(fid);
+	
+	/*thread_id_t tid;
+	if (0 != thread_create(init_running_drv, driver, "init_running_drv", &tid)) {
+		printf(NAME ": failed to start the initialization of the newly registered running driver.\n");
+	}*/
+	
+	ipc_callid_t callid;
+	ipc_call_t call;
+	bool cont = true;
+	while (cont) {
+		callid = async_get_call(&call);
+		
+		switch (IPC_GET_METHOD(call)) {
+		case IPC_M_PHONE_HUNGUP:
+			cont = false;
+			continue;
+		case DEVMAN_ADD_CHILD_DEVICE:
+			devman_add_child(callid, &call);
+			break;
+		case DEVMAN_ADD_DEVICE_TO_CLASS:
+			devman_add_device_to_class(callid, &call);
+			break;
+		default:
+			ipc_answer_0(callid, EINVAL); 
+			break;
+		}
+	}
+}
+
+/** Find handle for the device instance identified by the device's path in the device tree.
+ */
+static void devman_device_get_handle(ipc_callid_t iid, ipc_call_t *icall)
+{
+	char *pathname;	
+	int rc = async_data_write_accept((void **)&pathname, true, 0, 0, 0, 0);
+	if (rc != EOK) {
+		ipc_answer_0(iid, rc);
+		return;
+	}
+	
+	node_t * dev = find_dev_node_by_path(&device_tree, pathname); 
+	
+	free(pathname);
+
+	if (NULL == dev) {
+		ipc_answer_0(iid, ENOENT);
+		return;
+	}
+	
+	ipc_answer_1(iid, EOK, dev->handle);
+}
+
+
+/** Function for handling connections from a client to the device manager.
+ */
+static void devman_connection_client(ipc_callid_t iid, ipc_call_t *icall)
+{
+	/* Accept connection */
+	ipc_answer_0(iid, EOK);
+	
+	bool cont = true;
+	while (cont) {
+		ipc_call_t call;
+		ipc_callid_t callid = async_get_call(&call);
+		
+		switch (IPC_GET_METHOD(call)) {
+		case IPC_M_PHONE_HUNGUP:
+			cont = false;
+			continue;
+		case DEVMAN_DEVICE_GET_HANDLE:
+			devman_device_get_handle(callid, &call);
+			break;
+		default:
+			if (!(callid & IPC_CALLID_NOTIFICATION))
+				ipc_answer_0(callid, ENOENT);
+		}
+	}	
+}
+
+static void devman_forward(ipc_callid_t iid, ipc_call_t *icall, bool drv_to_parent) {	
+	
+	device_handle_t handle = IPC_GET_ARG2(*icall);
+	// printf(NAME ": devman_forward - trying to forward connection to device with handle %x.\n", handle);
+	
+	node_t *dev = find_dev_node(&device_tree, handle);
+	if (NULL == dev) {
+		printf(NAME ": devman_forward error - no device with handle %x was found.\n", handle);
+		ipc_answer_0(iid, ENOENT);
+		return;
+	}
+	
+	driver_t *driver = NULL;
+	
+	if (drv_to_parent) {
+		if (NULL != dev->parent) {
+			driver = dev->parent->drv;		
+		}
+	} else if (DEVICE_USABLE == dev->state) {
+		driver = dev->drv;		
+		assert(NULL != driver);
+	}
+	
+	if (NULL == driver) {	
+		printf(NAME ": devman_forward error - the device is not in usable state.\n", handle);
+		ipc_answer_0(iid, ENOENT);
+		return;	
+	}
+	
+	int method;	
+	if (drv_to_parent) {
+		method = DRIVER_DRIVER;
+	} else {
+		method = DRIVER_CLIENT;
+	}
+	
+	if (driver->phone <= 0) {
+		printf(NAME ": devman_forward: cound not forward to driver %s ", driver->name);
+		printf("the driver's phone is %x).\n", driver->phone);
+		ipc_answer_0(iid, EINVAL);
+		return;
+	}
+	printf(NAME ": devman_forward: forward connection to device %s to driver %s.\n", 
+		dev->pathname, driver->name);
+	ipc_forward_fast(iid, driver->phone, method, dev->handle, 0, IPC_FF_NONE);	
+}
+
+/** Function for handling connections from a client forwarded by the device mapper to the device manager.
+ */
+static void devman_connection_devmapper(ipc_callid_t iid, ipc_call_t *icall)
+{
+	dev_handle_t devmap_handle = IPC_GET_METHOD(*icall);
+	node_t *dev = find_devmap_tree_device(&device_tree, devmap_handle);
+	if (NULL == dev) {
+		dev = find_devmap_class_device(&class_list, devmap_handle);
+	}
+	
+	if (NULL == dev || NULL == dev->drv) {
+		ipc_answer_0(iid, ENOENT);
+		return;
+	}
+	
+	if (DEVICE_USABLE != dev->state || dev->drv->phone <= 0) {
+		ipc_answer_0(iid, EINVAL);
+		return;
+	}
+	
+	printf(NAME ": devman_connection_devmapper: forward connection to device %s to driver %s.\n", 
+		dev->pathname, dev->drv->name);
+	ipc_forward_fast(iid, dev->drv->phone, DRIVER_CLIENT, dev->handle, 0, IPC_FF_NONE);	
+}
+
+/** Function for handling connections to device manager.
+ *
+ */
+static void devman_connection(ipc_callid_t iid, ipc_call_t *icall)
+{	
+	// Silly hack to enable the device manager to register as a driver by the device mapper. 
+	// If the ipc method is not IPC_M_CONNECT_ME_TO, this is not the forwarded connection from naming service,
+	// so it must be a connection from the devmapper which thinks this is a devmapper-style driver. 
+	// So pretend this is a devmapper-style driver. 
+	// (This does not work for device with handle == IPC_M_CONNECT_ME_TO, 
+	// because devmapper passes device handle to the driver as an ipc method.)
+	if (IPC_M_CONNECT_ME_TO != IPC_GET_METHOD(*icall)) {
+		devman_connection_devmapper(iid, icall);
+	}
+
+	// ipc method is IPC_M_CONNECT_ME_TO, so this is forwarded connection from naming service
+	// by which we registered as device manager, so be device manager
+	
+	// Select interface 
+	switch ((ipcarg_t) (IPC_GET_ARG1(*icall))) {
+	case DEVMAN_DRIVER:
+		devman_connection_driver(iid, icall);
+		break;
+	case DEVMAN_CLIENT:
+		devman_connection_client(iid, icall);
+		break;
+	case DEVMAN_CONNECT_TO_DEVICE:
+		// Connect client to selected device
+		devman_forward(iid, icall, false);
+		break;
+	case DEVMAN_CONNECT_TO_PARENTS_DEVICE:
+		// Connect client to selected device
+		devman_forward(iid, icall, true);
+		break;		
+	default:
+		/* No such interface */
+		ipc_answer_0(iid, ENOENT);
+	}
+}
+
+/** Initialize device manager internal structures.
+ */
+static bool devman_init()
+{
+	printf(NAME ": devman_init - looking for available drivers. \n");	
+	
+	// initialize list of available drivers
+	init_driver_list(&drivers_list);
+	if (0 == lookup_available_drivers(&drivers_list, DRIVER_DEFAULT_STORE)) {
+		printf(NAME " no drivers found.");
+		return false;
+	}
+	printf(NAME ": devman_init  - list of drivers has been initialized. \n");
+
+	// create root device node 
+	if (!init_device_tree(&device_tree, &drivers_list)) {
+		printf(NAME " failed to initialize device tree.");
+		return false;		
+	}
+
+	init_class_list(&class_list);
+	
+	// !!! devman_connection ... as the device manager is not a real devmap driver 
+	// (it uses a completely different ipc protocol than an ordinary devmap driver)
+	// forwarding a connection from client to the devman by devmapper would not work
+	devmap_driver_register(NAME, devman_connection);	
+	
+	return true;
+}
+
+int main(int argc, char *argv[])
+{
+	printf(NAME ": HelenOS Device Manager\n");
+
+	if (!devman_init()) {
+		printf(NAME ": Error while initializing service\n");
+		return -1;
+	}
+	
+	// Set a handler of incomming connections
+	async_set_client_connection(devman_connection);
+
+	// Register device manager at naming service
+	ipcarg_t phonead;
+	if (ipc_connect_to_me(PHONE_NS, SERVICE_DEVMAN, 0, 0, &phonead) != 0)
+		return -1;
+
+	printf(NAME ": Accepting connections\n");
+	async_manager();
+
+	// Never reached
+	return 0;
+}
+
+/** @}
+ */
Index: uspace/srv/devman/match.c
===================================================================
--- uspace/srv/devman/match.c	(revision 04cb68f2d06da3440e206ec4339c4d23afa3910a)
+++ uspace/srv/devman/match.c	(revision 04cb68f2d06da3440e206ec4339c4d23afa3910a)
@@ -0,0 +1,92 @@
+/*
+ * Copyright (c) 2010 Lenka Trochtova
+ * 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 devman
+ * @{
+ */
+ 
+ 
+#include <str.h>
+
+#include "devman.h"
+
+
+int get_match_score(driver_t *drv, node_t *dev)
+{	
+	link_t* drv_head = &drv->match_ids.ids;	
+	link_t* dev_head = &dev->match_ids.ids;
+	
+	if (list_empty(drv_head) || list_empty(dev_head)) {
+		return 0;
+	}
+	
+	link_t* drv_link = drv->match_ids.ids.next;
+	link_t* dev_link = dev->match_ids.ids.next;
+	
+	match_id_t *drv_id = list_get_instance(drv_link, match_id_t, link);
+	match_id_t *dev_id = list_get_instance(dev_link, match_id_t, link);
+	
+	int score_next_drv = 0;
+	int score_next_dev = 0;
+	
+	do {
+		if (0 == str_cmp(drv_id->id, dev_id->id)) { 	// we found a match	
+			// return the score of the match
+			return drv_id->score * dev_id->score;
+		}
+		
+		// compute the next score we get, if we advance in the driver's list of match ids 
+		if (drv_head != drv_link->next) {
+			score_next_drv = dev_id->score * list_get_instance(drv_link->next, match_id_t, link)->score;			
+		} else {
+			score_next_drv = 0;
+		}
+		
+		// compute the next score we get, if we advance in the device's list of match ids 
+		if (dev_head != dev_link->next) {
+			score_next_dev = drv_id->score * list_get_instance(dev_link->next, match_id_t, link)->score;			
+		} else {
+			score_next_dev = 0;
+		}
+		
+		// advance in one of the two lists, so we get the next highest score
+		if (score_next_drv > score_next_dev) {
+			drv_link = drv_link->next;
+			drv_id = list_get_instance(drv_link, match_id_t, link);
+		} else {
+			dev_link = dev_link->next;
+			dev_id = list_get_instance(dev_link, match_id_t, link);
+		}
+		
+	} while (drv_head != drv_link->next && dev_head != dev_link->next);
+	
+	return 0;
+}
+
+
+
Index: uspace/srv/devman/util.c
===================================================================
--- uspace/srv/devman/util.c	(revision 04cb68f2d06da3440e206ec4339c4d23afa3910a)
+++ uspace/srv/devman/util.c	(revision 04cb68f2d06da3440e206ec4339c4d23afa3910a)
@@ -0,0 +1,70 @@
+/*
+ * Copyright (c) 2010 Lenka Trochtova
+ * 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 devman
+ * @{
+ */
+
+#include <stdlib.h>
+#include <str.h> 
+ 
+#include "util.h"
+ 
+
+char * get_abs_path(const char *base_path, const char *name, const char *ext) 
+{
+	char *res;
+	int base_len = str_size(base_path);
+	int size = base_len + 2*str_size(name) + str_size(ext) + 3;	
+	
+	res = malloc(size);
+	
+	if (res) {
+		str_cpy(res, size, base_path);
+		if(base_path[base_len - 1] != '/') { 
+			str_append(res, size, "/");			
+		}
+		str_append(res, size, name);
+		str_append(res, size, "/");
+		str_append(res, size, name);
+		if(ext[0] != '.') {
+			str_append(res, size, ".");
+		}
+		str_append(res, size, ext);		
+	}
+	
+	return res;
+}
+
+char * get_path_elem_end(char *path)
+{
+	while (0 != *path && '/' != *path) {
+		path++;
+	}
+	return path;
+}
Index: uspace/srv/devman/util.h
===================================================================
--- uspace/srv/devman/util.h	(revision 04cb68f2d06da3440e206ec4339c4d23afa3910a)
+++ uspace/srv/devman/util.h	(revision 04cb68f2d06da3440e206ec4339c4d23afa3910a)
@@ -0,0 +1,89 @@
+/*
+ * Copyright (c) 2010 Lenka Trochtova
+ * 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 devman
+ * @{
+ */
+ 
+#ifndef DEVMAN_UTIL_H_
+#define DEVMAN_UTIL_H_
+
+#include <ctype.h>
+#include <str.h>
+#include <malloc.h>
+
+
+char * get_abs_path(const char *base_path, const char *name, const char *ext);
+char * get_path_elem_end(char *path);
+
+static inline bool skip_spaces(char **buf) 
+{
+	while (isspace(**buf)) {
+		(*buf)++;		
+	}
+	return *buf != 0;	
+}
+
+static inline size_t get_nonspace_len(const char *str) 
+{
+	size_t len = 0;
+	while(*str != 0 && !isspace(*str)) {
+		len++;
+		str++;
+	}
+	return len;
+}
+
+static inline void free_not_null(const void *ptr)
+{
+	if (NULL != ptr) {
+		free(ptr);
+	}
+}
+
+static inline char * clone_string(const char *s) 
+{
+	size_t size = str_size(s) + 1;
+	char *str = (char *)malloc(size);
+	if (NULL != str) {
+		str_cpy(str, size, s);
+	}
+	return str;
+}
+
+static inline void replace_char(char *str, char orig, char repl)
+{
+	while (*str) {
+		if (orig == *str) {
+			*str = repl;
+		}
+		str++;
+	}
+}
+
+#endif
Index: uspace/srv/drivers/isa/Makefile
===================================================================
--- uspace/srv/drivers/isa/Makefile	(revision 04cb68f2d06da3440e206ec4339c4d23afa3910a)
+++ uspace/srv/drivers/isa/Makefile	(revision 04cb68f2d06da3440e206ec4339c4d23afa3910a)
@@ -0,0 +1,36 @@
+# Copyright (c) 2010 Lenka Trochtova
+# 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 = isa
+
+SOURCES = \
+	isa.c
+
+include $(USPACE_PREFIX)/Makefile.common
Index: uspace/srv/drivers/isa/isa.c
===================================================================
--- uspace/srv/drivers/isa/isa.c	(revision 04cb68f2d06da3440e206ec4339c4d23afa3910a)
+++ uspace/srv/drivers/isa/isa.c	(revision 04cb68f2d06da3440e206ec4339c4d23afa3910a)
@@ -0,0 +1,502 @@
+/*
+ * Copyright (c) 2010 Lenka Trochtova
+ * 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 isa ISA bus driver.
+ * @brief HelenOS ISA bus driver.
+ * @{
+ */
+
+/** @file
+ */
+
+#include <assert.h>
+#include <stdio.h>
+#include <errno.h>
+#include <bool.h>
+#include <fibril_synch.h>
+#include <stdlib.h>
+#include <str.h>
+#include <ctype.h>
+#include <macros.h>
+#include <malloc.h>
+#include <dirent.h>
+#include <fcntl.h>
+#include <sys/stat.h>
+
+#include <driver.h>
+#include <resource.h>
+
+#include <devman.h>
+#include <ipc/devman.h>
+#include <device/hw_res.h>
+
+#define NAME "isa"
+#define CHILD_DEV_CONF_PATH "/srv/drivers/isa/isa.dev"
+
+#define ISA_MAX_HW_RES 4
+
+typedef struct isa_child_data {
+	hw_resource_list_t hw_resources;	
+} isa_child_data_t;
+
+static hw_resource_list_t * isa_get_child_resources(device_t *dev)
+{
+	isa_child_data_t *dev_data = (isa_child_data_t *)dev->driver_data;
+	if (NULL == dev_data) {
+		return NULL;
+	}
+	return &dev_data->hw_resources;
+}
+
+static bool isa_enable_child_interrupt(device_t *dev) 
+{
+	// TODO
+	
+	return false;
+}
+
+static resource_iface_t isa_child_res_iface = {
+	&isa_get_child_resources,
+	&isa_enable_child_interrupt	
+};
+
+static device_ops_t isa_child_dev_ops;
+
+static int isa_add_device(device_t *dev);
+
+/** The isa device driver's standard operations.
+ */
+static driver_ops_t isa_ops = {
+	.add_device = &isa_add_device
+};
+
+/** The isa device driver structure. 
+ */
+static driver_t isa_driver = {
+	.name = NAME,
+	.driver_ops = &isa_ops
+};
+
+
+static isa_child_data_t * create_isa_child_data() 
+{
+	 isa_child_data_t *data = (isa_child_data_t *) malloc(sizeof(isa_child_data_t));
+	 if (NULL != data) {
+		 memset(data, 0, sizeof(isa_child_data_t));
+	 }
+	 return data;	
+}
+
+static device_t * create_isa_child_dev()
+{
+	device_t *dev = create_device();
+	if (NULL == dev) {
+		return NULL;
+	}
+	isa_child_data_t *data = create_isa_child_data();
+	if (NULL == data) {
+		delete_device(dev);
+		return NULL;
+	}
+	
+	dev->driver_data = data;
+	return dev;
+}
+
+static char * read_dev_conf(const char *conf_path)
+{		
+	bool suc = false;	
+	char *buf = NULL;
+	bool opened = false;
+	int fd;		
+	size_t len = 0;
+	
+	fd = open(conf_path, O_RDONLY);
+	if (fd < 0) {
+		printf(NAME ": unable to open %s\n", conf_path);
+		goto cleanup;
+	} 
+	opened = true;	
+	
+	len = lseek(fd, 0, SEEK_END);
+	lseek(fd, 0, SEEK_SET);	
+	if (len == 0) {
+		printf(NAME ": read_dev_conf error: configuration file '%s' is empty.\n", conf_path);
+		goto cleanup;		
+	}
+	
+	buf = malloc(len + 1);
+	if (buf == NULL) {
+		printf(NAME ": read_dev_conf error: memory allocation failed.\n");
+		goto cleanup;
+	}	
+	
+	if (0 >= read(fd, buf, len)) {
+		printf(NAME ": read_dev_conf error: unable to read file '%s'.\n", conf_path);
+		goto cleanup;
+	}
+	buf[len] = 0;
+	
+	suc = true;
+	
+cleanup:
+	
+	if (!suc && NULL != buf) {
+		free(buf);	
+		buf = NULL;
+	}
+	
+	if(opened) {
+		close(fd);	
+	}
+	
+	return buf;	
+}
+
+static char * str_get_line(char *str, char **next) {	
+	char *line = str;
+	
+	if (NULL == str) {
+		*next = NULL;
+		return NULL;
+	}
+	
+	while (0 != *str && '\n' != *str) {
+		str++;
+	} 
+	
+	if (0 != *str) {
+		*next = str + 1;
+	} else {
+		*next = NULL;
+	}	
+	
+	*str = 0;
+	
+	return line;
+}
+
+
+static bool line_empty(const char *line)
+{
+	while (NULL != line && 0 != *line) {
+		if(!isspace(*line)) {
+			return false;
+		}		
+		line++;		
+	}	
+	return true;	
+}
+
+static char * get_device_name(char *line) {
+	// skip leading spaces
+	while (0 != *line && isspace(*line)) {
+		line++;
+	}
+	
+	// get the name part of the rest of the line
+	strtok(line, ":");	
+	
+	// alloc output buffer
+	size_t size = str_size(line) + 1;
+	char *name = malloc(size);
+	
+	if (NULL != name) {
+		// copy the result to the output buffer
+		str_cpy(name, size, line);
+	}
+
+	return name;
+}
+
+static inline char * skip_spaces(char *line) 
+{
+	// skip leading spaces
+	while (0 != *line && isspace(*line)) {
+		line++;
+	}
+	return line;	
+}
+
+
+static void isa_child_set_irq(device_t *dev, int irq)
+{
+	isa_child_data_t *data = (isa_child_data_t *)dev->driver_data;
+	
+	size_t count = data->hw_resources.count;
+	hw_resource_t *resources = data->hw_resources.resources;
+	
+	if (count < ISA_MAX_HW_RES) {
+		resources[count].type = INTERRUPT;
+		resources[count].res.interrupt.irq = irq;
+		
+		data->hw_resources.count++;
+		
+		printf(NAME ": added irq 0x%x to device %s\n", irq, dev->name);
+	}	
+}
+
+static void isa_child_set_io_range(device_t *dev, size_t addr, size_t len)
+{
+	isa_child_data_t *data = (isa_child_data_t *)dev->driver_data;
+	
+	size_t count = data->hw_resources.count;
+	hw_resource_t *resources = data->hw_resources.resources;
+	
+	if (count < ISA_MAX_HW_RES) {
+		resources[count].type = IO_RANGE;
+		resources[count].res.io_range.address = addr;
+		resources[count].res.io_range.size = len;
+		resources[count].res.io_range.endianness = LITTLE_ENDIAN;	
+		
+		data->hw_resources.count++;
+		
+		printf(NAME ": added io range (addr=0x%x, size=0x%x) to device %s\n", addr, len, dev->name);
+	}	
+}
+
+static void get_dev_irq(device_t *dev, char *val)
+{
+	int irq = 0;
+	char *end = NULL;
+	
+	val = skip_spaces(val);	
+	irq = (int)strtol(val, &end, 0x10);
+	
+	if (val != end) {
+		isa_child_set_irq(dev, irq);		
+	}
+}
+
+static void get_dev_io_range(device_t *dev, char *val)
+{
+	size_t addr, len;
+	char *end = NULL;
+	
+	val = skip_spaces(val);	
+	addr = strtol(val, &end, 0x10);
+	
+	if (val == end) {
+		return;
+	}
+	
+	val = skip_spaces(end);	
+	len = strtol(val, &end, 0x10);
+	
+	if (val == end) {
+		return;
+	}
+	
+	isa_child_set_io_range(dev, addr, len);
+}
+
+static void get_match_id(char **id, char *val)
+{
+	char *end = val;
+	
+	while (!isspace(*end)) {
+		end++;
+	}		
+	size_t size = end - val + 1;
+	*id = (char *)malloc(size);
+	str_cpy(*id, size, val);	
+}
+
+static void get_dev_match_id(device_t *dev, char *val)
+{	
+	char *id = NULL;
+	int score = 0;
+	char *end = NULL;
+	
+	val = skip_spaces(val);	
+	
+	score = (int)strtol(val, &end, 10);
+	if (val == end) {
+		printf(NAME " : error - could not read match score for device %s.\n", dev->name);
+		return;
+	}
+	
+	match_id_t *match_id = create_match_id();
+	if (NULL == match_id) {
+		printf(NAME " : failed to allocate match id for device %s.\n", dev->name);
+		return;
+	}
+	
+	val = skip_spaces(end);	
+	get_match_id(&id, val);
+	if (NULL == id) {
+		printf(NAME " : error - could not read match id for device %s.\n", dev->name);
+		delete_match_id(match_id);
+		return;
+	}
+	
+	match_id->id = id;
+	match_id->score = score;
+	
+	printf(NAME ": adding match id '%s' with score %d to device %s\n", id, score, dev->name);
+	add_match_id(&dev->match_ids, match_id);
+}
+
+static bool read_dev_prop(
+	device_t *dev, char *line, const char *prop, void (* read_fn)(device_t *, char *)) 
+{
+	size_t proplen = str_size(prop);
+	if (0 == str_lcmp(line, prop, proplen)) {
+		line += proplen;
+		line = skip_spaces(line);
+		(*read_fn)(dev, line);
+		return true;
+	}
+	return false;		
+}
+
+static void get_dev_prop(device_t *dev, char *line)
+{
+	// skip leading spaces
+	line = skip_spaces(line);
+	
+	if (!read_dev_prop(dev, line, "io_range", &get_dev_io_range) &&
+		!read_dev_prop(dev, line, "irq", &get_dev_irq) &&
+		!read_dev_prop(dev, line, "match", &get_dev_match_id)
+	) {		
+		printf(NAME " error undefined device property at line '%s'\n", line);
+	} 	
+}
+
+static void child_alloc_hw_res(device_t *dev) 
+{
+	isa_child_data_t *data = (isa_child_data_t *)dev->driver_data;
+	data->hw_resources.resources = 
+		(hw_resource_t *)malloc(sizeof(hw_resource_t) * ISA_MAX_HW_RES);
+	
+}
+
+static char * read_isa_dev_info(char *dev_conf, device_t *parent)
+{
+	char *line;
+	char *dev_name = NULL;
+	
+	// skip empty lines
+	while (true) {	
+		line = str_get_line(dev_conf, &dev_conf);
+		
+		if (NULL == line) {
+			// no more lines
+			return NULL;
+		}
+		
+		if (!line_empty(line)) {
+			break;
+		}
+	}
+	
+	// get device name
+	dev_name = get_device_name(line);
+	if (NULL == dev_name) {
+		return NULL;
+	}
+	
+	device_t *dev = create_isa_child_dev();
+	if (NULL == dev) {
+		free(dev_name);
+		return NULL;
+	}
+	dev->name = dev_name;
+	
+	// allocate buffer for the list of hardware resources of the device
+	child_alloc_hw_res(dev);
+	
+	// get properties of the device (match ids, irq and io range)
+	while (true) {		
+		line = str_get_line(dev_conf, &dev_conf);		
+		
+		if (line_empty(line)) {
+			// no more device properties
+			break;
+		}
+		
+		// get the device's property from the configuration line and store it in the device structure
+		get_dev_prop(dev, line);
+		
+		//printf(NAME ": next line ='%s'\n", dev_conf);
+		//printf(NAME ": current line ='%s'\n", line);		
+	}
+	
+	// set device operations to the device
+	dev->ops = &isa_child_dev_ops;
+	
+	printf(NAME ": child_device_register(dev, parent); device is %s.\n", dev->name);
+	child_device_register(dev, parent);	
+	
+	return dev_conf;	
+}
+
+static void parse_dev_conf(char *conf, device_t *parent)
+{
+	while (NULL != conf && 0 != *conf) {
+		conf = read_isa_dev_info(conf, parent);
+	}	
+}
+
+static void add_legacy_children(device_t *parent)
+{
+	char *dev_conf = read_dev_conf(CHILD_DEV_CONF_PATH); 
+	if (NULL != dev_conf) {
+		parse_dev_conf(dev_conf, parent);	
+		free(dev_conf);
+	}
+}
+
+static int isa_add_device(device_t *dev) 
+{
+	printf(NAME ": isa_add_device, device handle = %d\n", dev->handle);
+	
+	// add child devices	
+	add_legacy_children(dev);
+	printf(NAME ": finished the enumeration of legacy devices\n", dev->handle);
+	
+	return EOK;
+}
+
+static void isa_init() 
+{
+	isa_child_dev_ops.interfaces[HW_RES_DEV_IFACE] = &isa_child_res_iface;
+}
+
+int main(int argc, char *argv[])
+{
+	printf(NAME ": HelenOS ISA bus driver\n");	
+	isa_init();
+	return driver_main(&isa_driver);
+}
+
+/**
+ * @}
+ */
+ 
Index: uspace/srv/drivers/isa/isa.dev
===================================================================
--- uspace/srv/drivers/isa/isa.dev	(revision 04cb68f2d06da3440e206ec4339c4d23afa3910a)
+++ uspace/srv/drivers/isa/isa.dev	(revision 04cb68f2d06da3440e206ec4339c4d23afa3910a)
@@ -0,0 +1,15 @@
+com1:
+	match 100 isa/ns8250
+	irq 4
+	io_range 3f8 8
+
+com2:
+	match 100 isa/ns8250
+	irq 3
+	io_range 2f8 8
+
+keyboard:
+	match 100 isa/keyboard
+	irq 1
+	io_range 060 10
+	
Index: uspace/srv/drivers/isa/isa.ma
===================================================================
--- uspace/srv/drivers/isa/isa.ma	(revision 04cb68f2d06da3440e206ec4339c4d23afa3910a)
+++ uspace/srv/drivers/isa/isa.ma	(revision 04cb68f2d06da3440e206ec4339c4d23afa3910a)
@@ -0,0 +1,1 @@
+9 	pci/ven=8086&dev=7000
Index: uspace/srv/drivers/ns8250/Makefile
===================================================================
--- uspace/srv/drivers/ns8250/Makefile	(revision 04cb68f2d06da3440e206ec4339c4d23afa3910a)
+++ uspace/srv/drivers/ns8250/Makefile	(revision 04cb68f2d06da3440e206ec4339c4d23afa3910a)
@@ -0,0 +1,36 @@
+# Copyright (c) 2010 Lenka Trochtova
+# 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 = ns8250
+
+SOURCES = \
+	ns8250.c
+
+include $(USPACE_PREFIX)/Makefile.common
Index: uspace/srv/drivers/ns8250/cyclic_buffer.h
===================================================================
--- uspace/srv/drivers/ns8250/cyclic_buffer.h	(revision 04cb68f2d06da3440e206ec4339c4d23afa3910a)
+++ uspace/srv/drivers/ns8250/cyclic_buffer.h	(revision 04cb68f2d06da3440e206ec4339c4d23afa3910a)
@@ -0,0 +1,84 @@
+/*
+ * Copyright (c) 2010 Lenka Trochtova 
+ * 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 ns8250
+ * @{
+ */
+/** @file
+ */
+ 
+#ifndef CYCLIC_BUFFER_H
+#define CYCLIC_BUFFER_H
+
+#define BUF_LEN 256  // the length of the buffer
+
+typedef struct cyclic_buffer {
+	uint8_t buf[BUF_LEN];  // the buffer 
+	int start;
+	int cnt;
+}  cyclic_buffer_t; 
+
+// returns false if the buffer is full
+static inline bool buf_push_back(cyclic_buffer_t *buf, uint8_t item) 
+{
+	if (buf->cnt >= BUF_LEN) {
+		return false;
+	}
+	
+	int pos = (buf->start + buf->cnt) % BUF_LEN;
+	buf->buf[pos] = item;
+	buf->cnt++;
+	return true;
+}
+
+static inline bool buf_is_empty(cyclic_buffer_t *buf) 
+{
+	return buf->cnt == 0;
+}
+
+// call it on non empty buffer!
+static inline uint8_t buf_pop_front(cyclic_buffer_t *buf) 
+{
+	assert(!buf_is_empty(buf));
+	
+	uint8_t res = buf->buf[buf->start];
+	buf->start = (buf->start + 1) % BUF_LEN;	
+	buf->cnt--;
+	return res;
+}
+
+static inline void buf_clear(cyclic_buffer_t *buf) 
+{
+	buf->cnt = 0;
+}
+
+#endif
+
+/**
+ * @}
+ */
Index: uspace/srv/drivers/ns8250/ns8250.c
===================================================================
--- uspace/srv/drivers/ns8250/ns8250.c	(revision 04cb68f2d06da3440e206ec4339c4d23afa3910a)
+++ uspace/srv/drivers/ns8250/ns8250.c	(revision 04cb68f2d06da3440e206ec4339c4d23afa3910a)
@@ -0,0 +1,924 @@
+/*
+ * Copyright (c) 2010 Lenka Trochtova
+ * 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 ns8250 Serial port driver.
+ * @brief HelenOS serial port driver.
+ * @{
+ */
+
+/** @file
+ */
+
+#include <assert.h>
+#include <stdio.h>
+#include <errno.h>
+#include <bool.h>
+#include <fibril_synch.h>
+#include <stdlib.h>
+#include <str.h>
+#include <ctype.h>
+#include <macros.h>
+#include <malloc.h>
+#include <dirent.h>
+#include <fcntl.h>
+#include <sys/stat.h>
+#include <ddi.h>
+#include <libarch/ddi.h>
+
+#include <driver.h>
+#include <char.h>
+#include <resource.h>
+
+#include <devman.h>
+#include <ipc/devman.h>
+#include <device/hw_res.h>
+#include <ipc/serial_ctl.h>
+
+#include "cyclic_buffer.h"
+
+#define NAME "ns8250"
+
+#define REG_COUNT 7
+#define MAX_BAUD_RATE 115200
+#define DLAB_MASK (1 << 7)
+
+/** The number of bits of one data unit send by the serial port.*/
+typedef enum {
+	WORD_LENGTH_5,
+	WORD_LENGTH_6,
+	WORD_LENGTH_7,
+	WORD_LENGTH_8	
+} word_length_t;
+
+/** The number of stop bits used by the serial port. */
+typedef enum {
+	/** Use one stop bit. */
+	ONE_STOP_BIT,
+	/** 1.5 stop bits for word length 5, 2 stop bits otherwise. */
+	TWO_STOP_BITS	
+} stop_bit_t;
+
+/** The driver data for the serial port devices.
+ */
+typedef struct ns8250_dev_data {
+	/** Is there any client conntected to the device? */
+	bool client_connected;
+	/** The irq assigned to this device. */
+	int irq;
+	/** The base i/o address of the devices registers. */
+	uint32_t io_addr;
+	/** The i/o port used to access the serial ports registers. */
+	ioport8_t *port;
+	/** The buffer for incomming data.*/
+	cyclic_buffer_t input_buffer;
+	/** The fibril mutex for synchronizing the access to the device.*/
+	fibril_mutex_t mutex;		
+} ns8250_dev_data_t;
+
+/** Create driver data for a device.
+ * 
+ * @return the driver data. 
+ */
+static ns8250_dev_data_t * create_ns8250_dev_data()
+{
+	ns8250_dev_data_t *data = (ns8250_dev_data_t *)malloc(sizeof(ns8250_dev_data_t));
+	if (NULL != data) {
+		memset(data, 0, sizeof(ns8250_dev_data_t));
+		fibril_mutex_initialize(&data->mutex);
+	}
+	return data;	
+}
+
+/** Delete driver data.
+ * 
+ * @param data the driver data structure.
+ */
+static void delete_ns8250_dev_data(ns8250_dev_data_t *data) 
+{
+	if (NULL != data) {
+		free(data);
+	}
+}
+
+/** Find out if there is some incomming data available on the serial port.
+ * 
+ * @param port the base address of the serial port device's ports.
+ * @return true if there are data waiting to be read, false otherwise. 
+ */
+static bool ns8250_received(ioport8_t *port) 
+{
+   return (pio_read_8(port + 5) & 1) != 0;
+}
+
+/** Read one byte from the serial port.
+ * 
+ * @param port the base address of the serial port device's ports.
+ * @return the data read. 
+ */
+static uint8_t ns8250_read_8(ioport8_t *port) 
+{
+	return pio_read_8(port);
+}
+
+/** Find out wheter it is possible to send data.
+ * 
+ * @param port the base address of the serial port device's ports.
+ */
+static bool is_transmit_empty(ioport8_t *port) 
+{
+   return (pio_read_8(port + 5) & 0x20) != 0;
+}
+
+/** Write one character on the serial port.
+ * 
+ * @param port the base address of the serial port device's ports.
+ * @param c the character to be written to the serial port device.
+ */
+static void ns8250_write_8(ioport8_t *port, uint8_t c) 
+{
+	while (!is_transmit_empty(port)) 
+		;
+	
+	pio_write_8(port, c);
+}
+
+/** Read data from the serial port device.
+ * 
+ * @param dev the serial port device.
+ * @param buf the ouput buffer for read data.
+ * @param count the number of bytes to be read.
+ * 
+ * @return the number of bytes actually read on success, negative error number otherwise.
+ */
+static int ns8250_read(device_t *dev, char *buf, size_t count) 
+{
+	// printf(NAME ": ns8250_read %s\n", dev->name);
+	
+	int ret = EOK;
+	
+	ns8250_dev_data_t *data = (ns8250_dev_data_t *)dev->driver_data;
+	fibril_mutex_lock(&data->mutex);
+	
+	while (!buf_is_empty(&data->input_buffer) && (size_t)ret < count) {
+		buf[ret] = (char)buf_pop_front(&data->input_buffer);
+		ret++;
+	}
+	
+	fibril_mutex_unlock(&data->mutex);
+	
+	return ret;
+}
+
+/** Write a character to the serial port.
+ * 
+ * @param data the serial port device's driver data.
+ * @param c the character to be written. 
+ */
+static inline void ns8250_putchar(ns8250_dev_data_t *data, uint8_t c)
+{	
+	fibril_mutex_lock(&data->mutex);
+	ns8250_write_8(data->port, c);	
+	fibril_mutex_unlock(&data->mutex);
+}
+
+/** Write data to the serial port.
+ * 
+ * @param dev the serial port device.
+ * @param buf the data to be written.
+ * @param count the number of bytes to be written.
+ * 
+ * @return 0 on success.
+ */
+static int ns8250_write(device_t *dev, char *buf, size_t count) 
+{
+	ns8250_dev_data_t *data = (ns8250_dev_data_t *)dev->driver_data;
+	
+	size_t idx;
+	for (idx = 0; idx < count; idx++) {
+		ns8250_putchar(data, (uint8_t)buf[idx]);
+	}
+	
+	return 0;
+}
+
+static device_ops_t ns8250_dev_ops;
+
+/** The character interface's callbacks. 
+ */
+static char_iface_t ns8250_char_iface = {
+	.read = &ns8250_read,
+	.write = &ns8250_write
+};
+
+static int ns8250_add_device(device_t *dev);
+
+/** The serial port device driver's standard operations.
+ */
+static driver_ops_t ns8250_ops = {
+	.add_device = &ns8250_add_device
+};
+
+/** The serial port device driver structure. 
+ */
+static driver_t ns8250_driver = {
+	.name = NAME,
+	.driver_ops = &ns8250_ops
+};
+
+/** Clean up the serial port device structure.
+ * 
+ * @param dev the device structure.
+ */
+static void ns8250_dev_cleanup(device_t *dev)
+{
+	if (NULL != dev->driver_data) {
+		delete_ns8250_dev_data((ns8250_dev_data_t*)dev->driver_data);	
+		dev->driver_data = NULL;
+	}
+	
+	if (dev->parent_phone > 0) {
+		ipc_hangup(dev->parent_phone);
+		dev->parent_phone = 0;
+	}	
+}
+
+/** Enable the i/o ports of the device.
+ * 
+ * @param the serial port device.
+ * @return true on success, false otherwise.
+ */
+static bool ns8250_pio_enable(device_t *dev)
+{
+	printf(NAME ": ns8250_pio_enable %s\n", dev->name);
+	
+	ns8250_dev_data_t *data = (ns8250_dev_data_t *)dev->driver_data;
+	
+	// Gain control over port's registers.
+	if (pio_enable((void *)data->io_addr, REG_COUNT, (void **)(&data->port))) {  
+		printf(NAME ": error - cannot gain the port %lx for device %s.\n", data->io_addr, dev->name);
+		return false;
+	}
+	
+	return true;
+}
+
+/** Probe the serial port device for its presence.
+ * 
+ * @param dev the serial port device.
+ * @return true if the device is present, false otherwise.
+ */
+static bool ns8250_dev_probe(device_t *dev)
+{
+	printf(NAME ": ns8250_dev_probe %s\n", dev->name);
+	
+	ns8250_dev_data_t *data = (ns8250_dev_data_t *)dev->driver_data;
+	ioport8_t *port_addr = data->port;	
+	bool res = true;
+	uint8_t olddata;
+	
+	olddata = pio_read_8(port_addr + 4);
+	
+	pio_write_8(port_addr + 4, 0x10);
+	if (pio_read_8(port_addr + 6) & 0xf0) {
+		res = false;
+	}
+	
+	pio_write_8(port_addr + 4, 0x1f);
+	if ((pio_read_8(port_addr + 6) & 0xf0) != 0xf0) {
+		res = false;
+	}
+	
+	pio_write_8(port_addr + 4, olddata);
+	
+	if (!res) {
+		printf(NAME ": device %s is not present.\n", dev->name);
+	}
+	
+	return res;	
+}
+
+/** Initialize serial port device.
+ * 
+ * @param dev the serial port device.
+ * @return 0 on success, negative error number otherwise.
+ */
+static int ns8250_dev_initialize(device_t *dev)
+{
+	printf(NAME ": ns8250_dev_initialize %s\n", dev->name);
+	
+	int ret = EOK;
+	hw_resource_list_t hw_resources;
+	memset(&hw_resources, 0, sizeof(hw_resource_list_t));
+	
+	// allocate driver data for the device
+	ns8250_dev_data_t *data = create_ns8250_dev_data();	
+	if (NULL == data) {
+		return ENOMEM;
+	}
+	dev->driver_data = data;
+	
+	// connect to the parent's driver
+	dev->parent_phone = devman_parent_device_connect(dev->handle,  IPC_FLAG_BLOCKING);
+	if (dev->parent_phone <= 0) {
+		printf(NAME ": failed to connect to the parent driver of the device %s.\n", dev->name);
+		ret = EPARTY;
+		goto failed;
+	}
+	
+	// get hw resources
+	
+	if (!get_hw_resources(dev->parent_phone, &hw_resources)) {
+		printf(NAME ": failed to get hw resources for the device %s.\n", dev->name);
+		ret = EPARTY;
+		goto failed;
+	}	
+	
+	size_t i;
+	hw_resource_t *res;
+	bool irq = false;
+	bool ioport = false;
+	
+	for (i = 0; i < hw_resources.count; i++) {
+		res = &hw_resources.resources[i];
+		switch (res->type) {
+		case INTERRUPT:
+			data->irq = res->res.interrupt.irq;
+			irq = true;
+			printf(NAME ": the %s device was asigned irq = 0x%x.\n", dev->name, data->irq);
+			break;
+		case IO_RANGE:
+			data->io_addr = res->res.io_range.address;
+			if (res->res.io_range.size < REG_COUNT) {
+				printf(NAME ": i/o range assigned to the device %s is too small.\n", dev->name);
+				ret = EPARTY;
+				goto failed;
+			}
+			ioport = true;
+			printf(NAME ": the %s device was asigned i/o address = 0x%x.\n", dev->name, data->io_addr);
+			break;	
+		default:
+			break;
+		}
+	}
+	
+	if (!irq || !ioport) {
+		printf(NAME ": missing hw resource(s) for the device %s.\n", dev->name);
+		ret = EPARTY;
+		goto failed;
+	}		
+	
+	clean_hw_resource_list(&hw_resources);
+	return ret;
+	
+failed:
+	ns8250_dev_cleanup(dev);	
+	clean_hw_resource_list(&hw_resources);	
+	return ret;	
+}
+
+/** Enable interrupts on the serial port device.
+ * 
+ * Interrupt when data is received.
+ * 
+ * @param port the base address of the serial port device's ports. 
+ */
+static inline void ns8250_port_interrupts_enable(ioport8_t *port)
+{	
+	pio_write_8(port + 1 , 0x01);   // Interrupt when data received
+	pio_write_8(port + 4, 0x0B);	
+}
+
+/** Disable interrupts on the serial port device.
+ * 
+ * @param port the base address of the serial port device's ports. 
+ */
+static inline void ns8250_port_interrupts_disable(ioport8_t *port)
+{
+	pio_write_8(port + 1, 0x00);    // Disable all interrupts
+}
+
+/** Enable interrupts for the serial port device.
+ * 
+ * @param dev the device.
+ * @return 0 on success, negative error number otherwise.
+ */
+static int ns8250_interrupt_enable(device_t *dev)
+{
+	ns8250_dev_data_t *data = (ns8250_dev_data_t *)dev->driver_data;
+	
+	int res;
+	// enable interrupt globally	
+	if (EOK != (res = interrupt_enable(data->irq))) {
+		return res;
+	}
+	
+	// enable interrupt on the serial port
+	ns8250_port_interrupts_enable(data->port);
+	
+	return EOK;
+}
+
+/** Set Divisor Latch Access Bit.
+ * 
+ * When the Divisor Latch Access Bit is set, 
+ * it is possible to set baud rate of the serial port device.
+ * 
+ * @param port the base address of the serial port device's ports. 
+ */
+static inline void enable_dlab(ioport8_t *port)
+{
+	uint8_t val = pio_read_8(port + 3);
+	pio_write_8(port + 3, val | DLAB_MASK);	
+}
+
+/** Clear Divisor Latch Access Bit.
+ * 
+ * @param port the base address of the serial port device's ports. 
+ */
+static inline void clear_dlab(ioport8_t *port)
+{
+	uint8_t val = pio_read_8(port + 3);
+	pio_write_8(port + 3, val & (~DLAB_MASK));
+}
+
+/** Set baud rate of the serial communication on the serial device.
+ * 
+ * @param port the base address of the serial port device's ports. 
+ * @param baud_rate the baud rate to be used by the device.
+ * 
+ * @return 0 on success, negative error number otherwise (EINVAL if the specified baud_rate is not valid). 
+ */
+static int ns8250_port_set_baud_rate(ioport8_t *port, unsigned int baud_rate)
+{
+	uint16_t divisor;
+	uint8_t div_low, div_high;
+	
+	if (50 > baud_rate || 0 != MAX_BAUD_RATE % baud_rate) {
+		printf(NAME ": error - somebody tried to set invalid baud rate %d\n", baud_rate);
+		return EINVAL; 
+	}
+	
+	divisor = MAX_BAUD_RATE / baud_rate;
+	div_low = (uint8_t)divisor;
+	div_high = (uint8_t)(divisor >> 8);	
+	
+	// enable DLAB to be able to access baud rate divisor
+	enable_dlab(port);    
+	
+	// set divisor low byte
+	pio_write_8(port + 0, div_low); 
+	// set divisor high byte
+	pio_write_8(port + 1, div_high);    
+	
+	clear_dlab(port);	
+	
+	return EOK;		
+}
+
+/** Get baud rate used by the serial port device.
+ * 
+ * @param port the base address of the serial port device's ports.
+ * @param baud_rate the ouput parameter to which the baud rate is stored.
+ */
+static unsigned int ns8250_port_get_baud_rate(ioport8_t *port)
+{
+	uint16_t divisor;
+	uint8_t div_low, div_high;
+	
+	// enable DLAB to be able to access baud rate divisor
+	enable_dlab(port);
+	
+	// get divisor low byte
+	div_low = pio_read_8(port + 0);
+	// get divisor high byte
+	div_high = pio_read_8(port + 1);   
+	
+	clear_dlab(port);
+	
+	divisor = (div_high << 8) | div_low;
+	return MAX_BAUD_RATE / divisor;
+}
+
+/** Get the parameters of the serial communication set on the serial port device.
+ * 
+ * @param parity the parity used.
+ * @param word_length the length of one data unit in bits.
+ * @param stop_bits the number of stop bits used (one or two). 
+ */
+static void ns8250_port_get_com_props(
+	ioport8_t *port, unsigned int *parity, unsigned int *word_length, unsigned int *stop_bits)
+{
+	uint8_t val;
+	
+	val = pio_read_8(port + 3);
+	
+	*parity = ((val >> 3) & 7);
+	
+	switch (val & 3) {
+		case WORD_LENGTH_5:
+			*word_length = 5;
+			break;
+		case WORD_LENGTH_6:
+			*word_length = 6;
+			break;
+		case WORD_LENGTH_7:
+			*word_length = 7;
+			break;
+		case WORD_LENGTH_8:
+			*word_length = 8;
+			break;
+	}
+	
+	if ((val >> 2) & 1) {
+		*stop_bits = 2;
+	} else {
+		*stop_bits = 1;
+	}	
+}
+
+/** Set the parameters of the serial communication on the serial port device.
+ * 
+ * @param parity the parity to be used.
+ * @param word_length the length of one data unit in bits.
+ * @param stop_bits the number of stop bits used (one or two). 
+ * 
+ * @return 0 on success, EINVAL if some of the specified values is invalid.
+ */
+static int ns8250_port_set_com_props(
+	ioport8_t *port, unsigned int parity, unsigned int word_length, unsigned int stop_bits)
+{
+	uint8_t val;
+	
+	switch (word_length) {
+		case 5:
+			val = WORD_LENGTH_5;
+			break;
+		case 6:
+			val = WORD_LENGTH_6;
+			break;
+		case 7:
+			val = WORD_LENGTH_7;
+			break;
+		case 8:
+			val = WORD_LENGTH_8;
+			break;
+		default:
+			return EINVAL;
+	}
+	
+	switch (stop_bits) {
+		case 1:
+			val |= ONE_STOP_BIT << 2;
+			break;
+		case 2:
+			val |= TWO_STOP_BITS << 2;
+			break;
+		default:
+			return EINVAL;
+	}
+	
+	switch (parity) {
+		case SERIAL_NO_PARITY:
+		case SERIAL_ODD_PARITY:
+		case SERIAL_EVEN_PARITY:
+		case SERIAL_MARK_PARITY:
+		case SERIAL_SPACE_PARITY:	
+			val |= parity << 3;
+			break;
+		default:
+			return EINVAL;
+	}
+	
+	pio_write_8(port + 3, val);	
+	
+	return EOK;
+}
+
+/** Initialize the serial port device.
+ * 
+ * Set the default parameters of the serial communication.
+ * 
+ * @param dev the serial port device.
+ */
+static void ns8250_initialize_port(device_t *dev)
+{
+	ns8250_dev_data_t *data = (ns8250_dev_data_t *)dev->driver_data;
+	ioport8_t *port = data->port;
+	
+	// disable interrupts
+	ns8250_port_interrupts_disable(port); 
+    // set baud rate
+	ns8250_port_set_baud_rate(port, 38400);
+	// 8 bits, no parity, two stop bits
+	ns8250_port_set_com_props(port, SERIAL_NO_PARITY, 8, 2);  
+	// Enable FIFO, clear them, with 14-byte threshold
+	pio_write_8(port + 2, 0xC7);  	
+	// RTS/DSR set (Request to Send and Data Terminal Ready lines enabled), 
+	// Aux Output2 set - needed for interrupts
+	pio_write_8(port + 4, 0x0B);    										
+}
+
+/** Read the data from the serial port device and store them to the input buffer.
+ * 
+ * @param dev the serial port device.
+ */
+static void ns8250_read_from_device(device_t *dev)
+{
+	ns8250_dev_data_t *data = (ns8250_dev_data_t *)dev->driver_data;
+	ioport8_t *port = data->port;
+	bool cont = true;
+	
+	while (cont) {	
+		fibril_mutex_lock(&data->mutex);
+		
+		cont = ns8250_received(port);
+		if (cont) {
+			uint8_t val = ns8250_read_8(port);
+			// printf(NAME ": character %c read from %s.\n", val, dev->name);			
+			
+			if (data->client_connected) {
+				if (!buf_push_back(&(data->input_buffer), val)) {
+					printf(NAME ": buffer overflow on %s.\n", dev->name);
+				} else {
+					printf(NAME ": the character %c saved to the buffer of %s.\n", val, dev->name);
+				}
+			} else {
+				// printf(NAME ": no client is connected to %s, discarding the character which was read.\n", dev->name);
+			}			
+		}
+		
+		fibril_mutex_unlock(&data->mutex);	
+		
+		fibril_yield();		
+	}	
+}
+
+/** The interrupt handler.
+ * 
+ * The serial port is initialized to interrupt when some data come, 
+ * so the interrupt is handled by reading the incomming data.
+ * 
+ * @param dev the serial port device. 
+ */
+static inline void ns8250_interrupt_handler(device_t *dev, ipc_callid_t iid, ipc_call_t *icall)
+{
+	ns8250_read_from_device(dev);
+}
+
+/** Register the interrupt handler for the device.
+ * 
+ * @param dev the serial port device.
+ */
+static inline int ns8250_register_interrupt_handler(device_t *dev)
+{
+	ns8250_dev_data_t *data = (ns8250_dev_data_t *)dev->driver_data;
+	
+	return register_interrupt_handler(dev, data->irq, ns8250_interrupt_handler, NULL);	
+}
+
+/** Unregister the interrupt handler for the device.
+ * 
+ * @param dev the serial port device.
+ */
+static inline int ns8250_unregister_interrupt_handler(device_t *dev)
+{
+	ns8250_dev_data_t *data = (ns8250_dev_data_t *)dev->driver_data;
+	
+	return unregister_interrupt_handler(dev, data->irq);	
+}
+
+/** The add_device callback method of the serial port driver.
+ * 
+ * Probe and initialize the newly added device.
+ * 
+ * @param dev the serial port device. 
+ */
+static int ns8250_add_device(device_t *dev) 
+{
+	printf(NAME ": ns8250_add_device %s (handle = %d)\n", dev->name, dev->handle);
+	
+	int res = ns8250_dev_initialize(dev);
+	if (EOK != res) {
+		return res;
+	}
+	
+	if (!ns8250_pio_enable(dev)) {
+		ns8250_dev_cleanup(dev);
+		return EADDRNOTAVAIL;
+	}	
+	
+	// find out whether the device is present
+	if (!ns8250_dev_probe(dev)) {
+		ns8250_dev_cleanup(dev);
+		return ENOENT;
+	}	
+	
+	// serial port initialization (baud rate etc.)
+	ns8250_initialize_port(dev);
+	
+	// register interrupt handler
+	if (EOK != ns8250_register_interrupt_handler(dev)) {
+		printf(NAME ": failed to register interrupt handler.\n");
+		ns8250_dev_cleanup(dev);
+		return res;
+	}
+	
+	// enable interrupt
+	if (EOK != (res = ns8250_interrupt_enable(dev))) {
+		printf(NAME ": failed to enable the interrupt. Error code = %d.\n", res);
+		ns8250_dev_cleanup(dev);
+		ns8250_unregister_interrupt_handler(dev);
+		return res;
+	}	
+	
+	// set device operations
+	dev->ops = &ns8250_dev_ops;
+	
+	add_device_to_class(dev, "serial");
+	
+	printf(NAME ": the %s device has been successfully initialized.\n", dev->name);
+	
+	return EOK;
+}
+
+/** Open the device.
+ * 
+ * This is a callback function called when a client tries to connect to the device.
+ * 
+ * @param dev the device.
+ */
+static int ns8250_open(device_t *dev)
+{
+	ns8250_dev_data_t *data = (ns8250_dev_data_t *)dev->driver_data;
+	int res;
+	
+	fibril_mutex_lock(&data->mutex);	
+	
+	if (data->client_connected) {
+		res = ELIMIT;
+	} else {
+		res = EOK;
+		data->client_connected = true;
+	}
+	
+	fibril_mutex_unlock(&data->mutex);
+
+	return res;
+}
+
+/** Close the device.
+ * 
+ *  This is a callback function called when a client tries to disconnect from the device.
+ * 
+ * @param dev the device. 
+ */
+static void ns8250_close(device_t *dev)
+{
+	ns8250_dev_data_t *data = (ns8250_dev_data_t *)dev->driver_data;
+	
+	fibril_mutex_lock(&data->mutex);
+	
+	assert(data->client_connected);	
+	
+	data->client_connected = false;
+	buf_clear(&data->input_buffer);
+	
+	fibril_mutex_unlock(&data->mutex);	 
+}
+
+/** Get parameters of the serial communication which are set to the specified device.
+ * 
+ * @param the serial port device.
+ * @param baud_rate the baud rate used by the device.
+ * @param the type of parity used by the device.
+ * @param word_length the size of one data unit in bits.
+ * @param stop_bits the number of stop bits used.
+ */
+static void ns8250_get_props(device_t *dev, unsigned int *baud_rate, 
+	unsigned int *parity, unsigned int *word_length, unsigned int* stop_bits)
+{	
+	ns8250_dev_data_t *data = (ns8250_dev_data_t *)dev->driver_data;
+	ioport8_t *port = data->port;
+	
+	fibril_mutex_lock(&data->mutex);	
+	ns8250_port_interrupts_disable(port);    // Disable all interrupts
+	*baud_rate = ns8250_port_get_baud_rate(port);
+	ns8250_port_get_com_props(port, parity, word_length, stop_bits);	
+	ns8250_port_interrupts_enable(port);
+	fibril_mutex_unlock(&data->mutex);	
+	
+	printf(NAME ": ns8250_get_props: baud rate %d, parity 0x%x, word length %d, stop bits %d\n", 
+		*baud_rate, *parity, *word_length, * stop_bits);
+}
+
+/** Set parameters of the serial communication to the specified  serial port device.
+ * 
+ * @param the serial port device.
+ * @param baud_rate the baud rate to be used by the device.
+ * @param the type of parity to be used by the device.
+ * @param word_length the size of one data unit in bits.
+ * @param stop_bits the number of stop bits to be used.
+ */
+static int ns8250_set_props(device_t *dev, unsigned int baud_rate, 
+	unsigned int parity, unsigned int word_length, unsigned int stop_bits)
+{
+	printf(NAME ": ns8250_set_props: baud rate %d, parity 0x%x, word length %d, stop bits %d\n", 
+		baud_rate, parity, word_length, stop_bits);
+	
+	ns8250_dev_data_t *data = (ns8250_dev_data_t *)dev->driver_data;
+	ioport8_t *port = data->port;
+	int ret;
+	
+	fibril_mutex_lock(&data->mutex);	
+	ns8250_port_interrupts_disable(port);    // Disable all interrupts
+	ret = ns8250_port_set_baud_rate(port, baud_rate);
+	if (EOK == ret) {
+		ret = ns8250_port_set_com_props(port, parity, word_length, stop_bits);
+	}
+	ns8250_port_interrupts_enable(port);
+	fibril_mutex_unlock(&data->mutex);	
+	
+	return ret;		
+}
+
+
+/** Default handler for client requests which are not handled by the standard interfaces.
+ * 
+ * Configure the parameters of the serial communication.
+ */
+static void ns8250_default_handler(device_t *dev, ipc_callid_t callid, ipc_call_t *call)
+{
+	ipcarg_t method = IPC_GET_METHOD(*call);
+	int ret;
+	unsigned int baud_rate, parity, word_length, stop_bits;	
+	
+	switch(method) {
+		case SERIAL_GET_COM_PROPS:
+			ns8250_get_props(dev, &baud_rate, &parity, &word_length, &stop_bits);
+			ipc_answer_4(callid, EOK, baud_rate, parity, word_length, stop_bits);
+			break;
+		
+		case SERIAL_SET_COM_PROPS:
+ 			baud_rate = IPC_GET_ARG1(*call);
+			parity = IPC_GET_ARG2(*call);
+			word_length = IPC_GET_ARG3(*call);
+			stop_bits = IPC_GET_ARG4(*call);
+			ret = ns8250_set_props(dev, baud_rate, parity, word_length, stop_bits);
+			ipc_answer_0(callid, ret);
+			break;
+			
+		default:
+			ipc_answer_0(callid, ENOTSUP);		
+	}	
+}
+
+/** Initialize the serial port driver.
+ * 
+ * Initialize device operations structures with callback methods for handling 
+ * client requests to the serial port devices.
+ */
+static void ns8250_init() 
+{
+	ns8250_dev_ops.open = &ns8250_open;
+	ns8250_dev_ops.close = &ns8250_close;	
+	
+	ns8250_dev_ops.interfaces[CHAR_DEV_IFACE] = &ns8250_char_iface;
+	ns8250_dev_ops.default_handler = &ns8250_default_handler;
+}
+
+int main(int argc, char *argv[])
+{
+	printf(NAME ": HelenOS serial port driver\n");	
+	ns8250_init();
+	return driver_main(&ns8250_driver);
+}
+
+/**
+ * @}
+ */
Index: uspace/srv/drivers/ns8250/ns8250.ma
===================================================================
--- uspace/srv/drivers/ns8250/ns8250.ma	(revision 04cb68f2d06da3440e206ec4339c4d23afa3910a)
+++ uspace/srv/drivers/ns8250/ns8250.ma	(revision 04cb68f2d06da3440e206ec4339c4d23afa3910a)
@@ -0,0 +1,1 @@
+10 isa/ns8250
Index: uspace/srv/drivers/pciintel/Makefile
===================================================================
--- uspace/srv/drivers/pciintel/Makefile	(revision 04cb68f2d06da3440e206ec4339c4d23afa3910a)
+++ uspace/srv/drivers/pciintel/Makefile	(revision 04cb68f2d06da3440e206ec4339c4d23afa3910a)
@@ -0,0 +1,36 @@
+# Copyright (c) 2010 Lenka Trochtova
+# 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 = pciintel
+
+SOURCES = \
+	pci.c
+
+include $(USPACE_PREFIX)/Makefile.common
Index: uspace/srv/drivers/pciintel/pci.c
===================================================================
--- uspace/srv/drivers/pciintel/pci.c	(revision 04cb68f2d06da3440e206ec4339c4d23afa3910a)
+++ uspace/srv/drivers/pciintel/pci.c	(revision 04cb68f2d06da3440e206ec4339c4d23afa3910a)
@@ -0,0 +1,505 @@
+/*
+ * Copyright (c) 2010 Lenka Trochtova
+ * 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 pciintel pci bus driver for intel method 1.
+ * @brief HelenOS root pci bus driver for intel method 1.
+ * @{
+ */
+
+/** @file
+ */
+
+#include <assert.h>
+#include <stdio.h>
+#include <errno.h>
+#include <bool.h>
+#include <fibril_synch.h>
+#include <str.h>
+#include <ctype.h>
+#include <macros.h>
+
+#include <driver.h>
+#include <devman.h>
+#include <ipc/devman.h>
+#include <ipc/dev_iface.h>
+#include <resource.h>
+#include <device/hw_res.h>
+#include <ddi.h>
+#include <libarch/ddi.h>
+
+#include "pci.h"
+
+#define NAME "pciintel"
+
+#define CONF_ADDR(bus, dev, fn, reg)   ((1 << 31) | (bus << 16) | (dev << 11) | (fn << 8) | (reg & ~3))
+
+
+static hw_resource_list_t * pciintel_get_child_resources(device_t *dev)
+{
+	pci_dev_data_t *dev_data = (pci_dev_data_t *)dev->driver_data;
+	if (NULL == dev_data) {
+		return NULL;
+	}
+	return &dev_data->hw_resources;
+}
+
+static bool pciintel_enable_child_interrupt(device_t *dev) 
+{
+	// TODO
+	
+	return false;
+}
+
+static resource_iface_t pciintel_child_res_iface = {
+	&pciintel_get_child_resources,
+	&pciintel_enable_child_interrupt	
+};
+
+static device_ops_t pci_child_ops;
+
+
+static int pci_add_device(device_t *dev);
+
+/** The pci bus driver's standard operations.
+ */
+static driver_ops_t pci_ops = {
+	.add_device = &pci_add_device
+};
+
+/** The pci bus driver structure. 
+ */
+static driver_t pci_driver = {
+	.name = NAME,
+	.driver_ops = &pci_ops
+};
+
+typedef struct pciintel_bus_data {
+	uint32_t conf_io_addr;
+	void *conf_data_port;
+	void *conf_addr_port;	
+	fibril_mutex_t conf_mutex;
+} pci_bus_data_t;
+
+static inline pci_bus_data_t *create_pci_bus_data() 
+{
+	pci_bus_data_t *bus_data = (pci_bus_data_t *)malloc(sizeof(pci_bus_data_t));
+	if(NULL != bus_data) {
+		memset(bus_data, 0, sizeof(pci_bus_data_t));
+		fibril_mutex_initialize(&bus_data->conf_mutex);
+	}
+	return bus_data;	
+}
+
+static inline void delete_pci_bus_data(pci_bus_data_t *bus_data) 
+{
+	free(bus_data);	
+}
+
+static void pci_conf_read(device_t *dev, int reg, uint8_t *buf, size_t len)
+{
+	assert(NULL != dev->parent);
+	
+	pci_dev_data_t *dev_data = (pci_dev_data_t *)dev->driver_data;
+	pci_bus_data_t *bus_data = (pci_bus_data_t *)dev->parent->driver_data;
+	
+	fibril_mutex_lock(&bus_data->conf_mutex);
+	
+	uint32_t conf_addr =  CONF_ADDR(dev_data->bus, dev_data->dev, dev_data->fn, reg);
+	void *addr = bus_data->conf_data_port + (reg & 3);
+	
+	pio_write_32(bus_data->conf_addr_port, conf_addr);
+	
+	switch (len) {
+		case 1:
+			buf[0] = pio_read_8(addr);
+			break;
+		case 2:
+			((uint16_t *)buf)[0] = pio_read_16(addr);
+			break;
+		case 4:
+			((uint32_t *)buf)[0] = pio_read_32(addr);
+			break;
+	}
+	
+	fibril_mutex_unlock(&bus_data->conf_mutex);	
+}
+
+static void pci_conf_write(device_t *dev, int reg, uint8_t *buf, size_t len)
+{
+	assert(NULL != dev->parent);
+	
+	pci_dev_data_t *dev_data = (pci_dev_data_t *)dev->driver_data;
+	pci_bus_data_t *bus_data = (pci_bus_data_t *)dev->parent->driver_data;
+	
+	fibril_mutex_lock(&bus_data->conf_mutex);
+	
+	uint32_t conf_addr =  CONF_ADDR(dev_data->bus, dev_data->dev, dev_data->fn, reg);
+	void *addr = bus_data->conf_data_port + (reg & 3);
+	
+	pio_write_32(bus_data->conf_addr_port, conf_addr);
+	
+	switch (len) {
+		case 1:
+			pio_write_8(addr, buf[0]);
+			break;
+		case 2:
+			pio_write_16(addr, ((uint16_t *)buf)[0]);
+			break;
+		case 4:
+			pio_write_32(addr, ((uint32_t *)buf)[0]);
+			break;
+	}
+	
+	fibril_mutex_unlock(&bus_data->conf_mutex);	
+}
+
+uint8_t pci_conf_read_8(device_t *dev, int reg)
+{
+	uint8_t res;
+	pci_conf_read(dev, reg, &res, 1);
+	return res;
+}
+
+uint16_t pci_conf_read_16(device_t *dev, int reg)
+{
+	uint16_t res;
+	pci_conf_read(dev, reg, (uint8_t *)&res, 2);
+	return res;
+}
+
+uint32_t pci_conf_read_32(device_t *dev, int reg)
+{
+	uint32_t res;
+	pci_conf_read(dev, reg, (uint8_t *)&res, 4);
+	return res;	
+}
+
+void pci_conf_write_8(device_t *dev, int reg, uint8_t val) 
+{
+	pci_conf_write(dev, reg, (uint8_t *)&val, 1);	
+}
+
+void pci_conf_write_16(device_t *dev, int reg, uint16_t val) 
+{
+	pci_conf_write(dev, reg, (uint8_t *)&val, 2);	
+}
+
+void pci_conf_write_32(device_t *dev, int reg, uint32_t val) 
+{
+	pci_conf_write(dev, reg, (uint8_t *)&val, 4);	
+}
+
+
+void create_pci_match_ids(device_t *dev)
+{
+	pci_dev_data_t *dev_data = (pci_dev_data_t *)dev->driver_data;
+	match_id_t *match_id = NULL;	
+	char *match_id_str;	
+	match_id = create_match_id();
+	if (NULL != match_id) {
+		asprintf(&match_id_str, "pci/ven=%04x&dev=%04x", dev_data->vendor_id, dev_data->device_id);
+		match_id->id = match_id_str;
+		match_id->score = 90;
+		add_match_id(&dev->match_ids, match_id);
+	}	
+	// TODO add more ids (with subsys ids, using class id etc.)
+}
+
+void pci_add_range(device_t *dev, uint64_t range_addr, size_t range_size, bool io)
+{
+	pci_dev_data_t *dev_data = (pci_dev_data_t *)dev->driver_data;
+	hw_resource_list_t *hw_res_list = &dev_data->hw_resources;
+	hw_resource_t *hw_resources =  hw_res_list->resources;
+	size_t count = hw_res_list->count;	
+	
+	assert(NULL != hw_resources);
+	assert(count < PCI_MAX_HW_RES);
+	
+	if (io) {
+		hw_resources[count].type = IO_RANGE;
+		hw_resources[count].res.io_range.address = range_addr;
+		hw_resources[count].res.io_range.size = range_size;	
+		hw_resources[count].res.io_range.endianness = LITTLE_ENDIAN;	
+	} else {
+		hw_resources[count].type = MEM_RANGE;
+		hw_resources[count].res.mem_range.address = range_addr;
+		hw_resources[count].res.mem_range.size = range_size;	
+		hw_resources[count].res.mem_range.endianness = LITTLE_ENDIAN;
+	}
+	
+	hw_res_list->count++;	
+}
+
+
+/** Read the base address register (BAR) of the device 
+ *  and if it contains valid address add it to the devices hw resource list.
+ * 
+ * @param dev the pci device.
+ * @param addr the address of the BAR in the PCI configuration address space of the device.
+ * 
+ * @return the addr the address of the BAR which should be read next.
+ */
+int pci_read_bar(device_t *dev, int addr) 
+{	
+	// value of the BAR
+	uint32_t val, mask;
+	// IO space address
+	bool io;
+	// 64-bit wide address
+	bool w64;
+	
+	// size of the io or memory range specified by the BAR
+	size_t range_size;
+	// beginning of the io or memory range specified by the BAR
+	uint64_t range_addr;
+	
+	// get the value of the BAR
+	val = pci_conf_read_32(dev, addr);
+	
+	io = (bool)(val & 1);
+	if (io) {
+		w64 = false;
+	} else {
+		switch ((val >> 1) & 3) {
+		case 0:
+			w64 = false;
+			break;
+		case 2:
+			w64 = true;
+			break;
+		default:
+			// reserved, go to the next BAR
+			return addr + 4;							
+		}
+	}
+	
+	// get the address mask
+	pci_conf_write_32(dev, addr, 0xffffffff);
+	mask = pci_conf_read_32(dev, addr);	
+	
+	// restore the original value
+	pci_conf_write_32(dev, addr, val);
+	val = pci_conf_read_32(dev, addr);	
+	
+	range_size = pci_bar_mask_to_size(mask);
+	
+	if (w64) {
+		range_addr = ((uint64_t)pci_conf_read_32(dev, addr + 4) << 32) | (val & 0xfffffff0);	
+	} else {
+		range_addr = (val & 0xfffffff0);
+	}	
+	if (0 != range_addr) {
+		printf(NAME ": device %s : ", dev->name);
+		printf("address = %x", range_addr);		
+		printf(", size = %x\n", range_size);
+	}
+	
+	pci_add_range(dev, range_addr, range_size, io);
+	
+	if (w64) {
+		return addr + 8;
+	}
+	return addr + 4;	
+}
+
+void pci_add_interrupt(device_t *dev, int irq)
+{
+	pci_dev_data_t *dev_data = (pci_dev_data_t *)dev->driver_data;
+	hw_resource_list_t *hw_res_list = &dev_data->hw_resources;
+	hw_resource_t *hw_resources =  hw_res_list->resources;
+	size_t count = hw_res_list->count;	
+	
+	assert(NULL != hw_resources);
+	assert(count < PCI_MAX_HW_RES);
+	
+	hw_resources[count].type = INTERRUPT;
+	hw_resources[count].res.interrupt.irq = irq;
+	
+	hw_res_list->count++;		
+	
+	
+	printf(NAME ": device %s uses irq %x.\n", dev->name, irq);
+}
+
+void pci_read_interrupt(device_t *dev)
+{
+	uint8_t irq = pci_conf_read_8(dev, PCI_BRIDGE_INT_LINE);
+	if (0xff != irq) {
+		pci_add_interrupt(dev, irq);
+	}	
+}
+
+/** Enumerate (recursively) and register the devices connected to a pci bus.
+ * 
+ * @param parent the host-to-pci bridge device.
+ * @param bus_num the bus number. 
+ */
+void pci_bus_scan(device_t *parent, int bus_num) 
+{
+	device_t *dev = create_device();
+	pci_dev_data_t *dev_data = create_pci_dev_data();
+	dev->driver_data = dev_data;
+	dev->parent = parent;
+	
+	int child_bus = 0;
+	int dnum, fnum;
+	bool multi;
+	uint8_t header_type; 
+	
+	for (dnum = 0; dnum < 32; dnum++) {
+		multi = true;
+		for (fnum = 0; multi && fnum < 8; fnum++) {
+			init_pci_dev_data(dev_data, bus_num, dnum, fnum);
+			dev_data->vendor_id = pci_conf_read_16(dev, PCI_VENDOR_ID);
+			dev_data->device_id = pci_conf_read_16(dev, PCI_DEVICE_ID);
+			if (dev_data->vendor_id == 0xffff) { // device is not present, go on scanning the bus
+				if (fnum == 0) {
+					break;
+				} else {
+					continue;  
+				}
+			}
+			header_type = pci_conf_read_8(dev, PCI_HEADER_TYPE);
+			if (fnum == 0) {
+				 multi = header_type >> 7;  // is the device multifunction?
+			}
+			header_type = header_type & 0x7F; // clear the multifunction bit
+			
+			create_pci_dev_name(dev);
+			
+			pci_alloc_resource_list(dev);
+			pci_read_bars(dev);
+			pci_read_interrupt(dev);
+			
+			dev->ops = &pci_child_ops;			
+			
+			printf(NAME ": adding new child device %s.\n", dev->name);
+			
+			create_pci_match_ids(dev);
+			
+			if (EOK != child_device_register(dev, parent)) {				
+				pci_clean_resource_list(dev);				
+				clean_match_ids(&dev->match_ids);
+				free((char *)dev->name);
+				dev->name = NULL;
+				continue;
+			}
+			
+			//printf(NAME ": new device %s was successfully registered by device manager.\n", dev->name);
+			
+			if (header_type == PCI_HEADER_TYPE_BRIDGE || header_type == PCI_HEADER_TYPE_CARDBUS ) {
+				child_bus = pci_conf_read_8(dev, PCI_BRIDGE_SEC_BUS_NUM);
+				printf(NAME ": device is pci-to-pci bridge, secondary bus number = %d.\n", bus_num);
+				if(child_bus > bus_num) {			
+					pci_bus_scan(parent, child_bus);	
+				}					
+			}
+			
+			dev = create_device();  // alloc new aux. dev. structure
+			dev_data = create_pci_dev_data();
+			dev->driver_data = dev_data;
+			dev->parent = parent;
+		}
+	}
+	
+	if (dev_data->vendor_id == 0xffff) {
+		delete_device(dev);
+		delete_pci_dev_data(dev_data);  // free the auxiliary device structure
+	}		
+}
+
+static int pci_add_device(device_t *dev)
+{
+	printf(NAME ": pci_add_device\n");
+	
+	pci_bus_data_t *bus_data = create_pci_bus_data();
+	if (NULL == bus_data) {
+		printf(NAME ": pci_add_device allocation failed.\n");
+		return ENOMEM;
+	}	
+	
+	dev->parent_phone = devman_parent_device_connect(dev->handle,  IPC_FLAG_BLOCKING);
+	if (dev->parent_phone <= 0) {
+		printf(NAME ": pci_add_device failed to connect to the parent's driver.\n");
+		delete_pci_bus_data(bus_data);
+		return EPARTY;
+	}
+	
+	hw_resource_list_t hw_resources;
+	
+	if (!get_hw_resources(dev->parent_phone, &hw_resources)) {
+		printf(NAME ": pci_add_device failed to get hw resources for the device.\n");
+		delete_pci_bus_data(bus_data);
+		ipc_hangup(dev->parent_phone);
+		return EPARTY;		
+	}	
+	
+	printf(NAME ": conf_addr = %x.\n", hw_resources.resources[0].res.io_range.address);	
+	
+	assert(hw_resources.count > 0);
+	assert(hw_resources.resources[0].type == IO_RANGE);
+	assert(hw_resources.resources[0].res.io_range.size == 8);
+	
+	bus_data->conf_io_addr = (uint32_t)hw_resources.resources[0].res.io_range.address;
+	
+	if (pio_enable((void *)bus_data->conf_io_addr, 8, &bus_data->conf_addr_port)) {
+		printf(NAME ": failed to enable configuration ports.\n");
+		delete_pci_bus_data(bus_data);
+		ipc_hangup(dev->parent_phone);
+		clean_hw_resource_list(&hw_resources);
+		return EADDRNOTAVAIL;					
+	}
+	bus_data->conf_data_port = (char *)bus_data->conf_addr_port + 4;
+	
+	dev->driver_data = bus_data;
+	
+	// enumerate child devices
+	printf(NAME ": scanning the bus\n");
+	pci_bus_scan(dev, 0);
+	
+	clean_hw_resource_list(&hw_resources);
+	
+	return EOK;
+}
+
+static void pciintel_init() 
+{
+	pci_child_ops.interfaces[HW_RES_DEV_IFACE] = &pciintel_child_res_iface;
+}
+
+int main(int argc, char *argv[])
+{
+	printf(NAME ": HelenOS pci bus driver (intel method 1).\n");
+	pciintel_init();
+	return driver_main(&pci_driver);
+}
+
+/**
+ * @}
+ */
Index: uspace/srv/drivers/pciintel/pci.h
===================================================================
--- uspace/srv/drivers/pciintel/pci.h	(revision 04cb68f2d06da3440e206ec4339c4d23afa3910a)
+++ uspace/srv/drivers/pciintel/pci.h	(revision 04cb68f2d06da3440e206ec4339c4d23afa3910a)
@@ -0,0 +1,147 @@
+/*
+ * Copyright (c) 2010 Lenka Trochtova 
+ * 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 pciintel
+ * @{
+ */
+/** @file
+ */
+ 
+#ifndef PCI_H
+#define PCI_H
+
+
+#include <stdlib.h>
+#include <driver.h>
+#include <malloc.h>
+
+#include "pci_regs.h"
+
+#define PCI_MAX_HW_RES 8
+
+typedef struct pci_dev_data {
+	int bus;
+	int dev;
+	int fn;
+	int vendor_id;
+	int device_id;
+	hw_resource_list_t hw_resources;
+} pci_dev_data_t;
+
+void create_pci_match_ids(device_t *dev);
+
+uint8_t pci_conf_read_8(device_t *dev, int reg);
+uint16_t pci_conf_read_16(device_t *dev, int reg);
+uint32_t pci_conf_read_32(device_t *dev, int reg);
+void pci_conf_write_8(device_t *dev, int reg, uint8_t val);
+void pci_conf_write_16(device_t *dev, int reg, uint16_t val);
+void pci_conf_write_32(device_t *dev, int reg, uint32_t val);
+
+void pci_add_range(device_t *dev, uint64_t range_addr, size_t range_size, bool io);
+int pci_read_bar(device_t *dev, int addr);
+void pci_read_interrupt(device_t *dev);
+void pci_add_interrupt(device_t *dev, int irq);
+
+void pci_bus_scan(device_t *parent, int bus_num);
+
+
+static inline pci_dev_data_t *create_pci_dev_data() 
+{
+	pci_dev_data_t *res = (pci_dev_data_t *)malloc(sizeof(pci_dev_data_t));
+	if (NULL != res) {
+		memset(res, 0, sizeof(pci_dev_data_t));
+	}
+	return res;	
+}
+
+static inline void init_pci_dev_data(pci_dev_data_t *d, int bus, int dev, int fn) 
+{
+	d->bus = bus;
+	d->dev = dev;
+	d->fn = fn;	
+}
+
+static inline void delete_pci_dev_data(pci_dev_data_t *d) 
+{
+	if (NULL != d) {
+		clean_hw_resource_list(&d->hw_resources);
+		free(d);	
+	}
+}
+
+static inline void create_pci_dev_name(device_t *dev)
+{
+	pci_dev_data_t *dev_data = (pci_dev_data_t *)dev->driver_data;
+	char *name = NULL;
+	asprintf(&name, "%02x:%02x.%01x", dev_data->bus, dev_data->dev, dev_data->fn);
+	dev->name = name;
+}
+
+static inline bool pci_alloc_resource_list(device_t *dev)
+{
+	pci_dev_data_t *dev_data = (pci_dev_data_t *)dev->driver_data;
+	dev_data->hw_resources.resources = (hw_resource_t *)malloc(PCI_MAX_HW_RES * sizeof(hw_resource_t));
+	return dev_data->hw_resources.resources != NULL;	
+}
+
+static inline void pci_clean_resource_list(device_t *dev)
+{
+	pci_dev_data_t *dev_data = (pci_dev_data_t *)dev->driver_data;
+	if (NULL != dev_data->hw_resources.resources) {
+		free(dev_data->hw_resources.resources);
+		dev_data->hw_resources.resources = NULL;
+	}
+}
+
+/** Read the base address registers (BARs) of the device 
+ *  and adds the addresses to its hw resource list.
+ * 
+ * @param dev the pci device.
+ */
+static inline  void pci_read_bars(device_t *dev)
+{
+	// position of the BAR in the PCI configuration address space of the device
+	int addr = PCI_BASE_ADDR_0;
+	
+	while (addr <= PCI_BASE_ADDR_5) {
+		addr = pci_read_bar(dev, addr);	
+	}	
+}
+
+static inline size_t pci_bar_mask_to_size(uint32_t mask)
+{
+	return ((mask & 0xfffffff0) ^ 0xffffffff) + 1;
+}
+
+
+#endif
+
+
+/**
+ * @}
+ */
Index: uspace/srv/drivers/pciintel/pci_regs.h
===================================================================
--- uspace/srv/drivers/pciintel/pci_regs.h	(revision 04cb68f2d06da3440e206ec4339c4d23afa3910a)
+++ uspace/srv/drivers/pciintel/pci_regs.h	(revision 04cb68f2d06da3440e206ec4339c4d23afa3910a)
@@ -0,0 +1,102 @@
+/*
+ * Copyright (c) 2010 Lenka Trochtova 
+ * 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 pciintel
+ * @{
+ */
+/** @file
+ */
+ 
+#ifndef PCI_REGS_H
+#define PCI_REGS_H
+
+// Header types 
+#define PCI_HEADER_TYPE_DEV			0
+#define PCI_HEADER_TYPE_BRIDGE		1
+#define PCI_HEADER_TYPE_CARDBUS		2
+
+// Header type 0 and 1
+#define PCI_VENDOR_ID		 			0x00
+#define PCI_DEVICE_ID 					0x02
+#define PCI_COMMAND 					0x04
+#define PCI_STATUS 						0x06
+#define PCI_REVISION_ID 				0x08
+#define PCI_PROG_IF						0x09
+#define PCI_SUB_CLASS					0x0A
+#define PCI_BASE_CLASS					0x0B
+#define PCI_CACHE_LINE_SIZE				0x0C
+#define PCI_LATENCY_TIMER				0x0D
+#define PCI_HEADER_TYPE					0x0E
+#define PCI_BIST						0x0F
+
+#define PCI_BASE_ADDR_0 				0x10
+#define PCI_BASE_ADDR_1 				0x14
+
+// Header type 0
+#define PCI_BASE_ADDR_2 				0x18
+#define PCI_BASE_ADDR_3 				0x1B
+#define PCI_BASE_ADDR_4 				0x20
+#define PCI_BASE_ADDR_5 				0x24
+
+#define PCI_CARDBUS_CIS_PTR				0x28
+#define PCI_SUBSYSTEM_VENDOR_ID			0x2C
+#define PCI_SUBSYSTEM_ID				0x2E
+#define PCI_EXP_ROM_BASE				0x30
+#define PCI_CAP_PTR						0x34
+#define PCI_INT_LINE					0x3C
+#define PCI_INT_PIN						0x3D
+#define PCI_MIN_GNT						0x3E
+#define PCI_MAX_LAT						0x3F
+
+// Header type 1
+#define PCI_BRIDGE_PRIM_BUS_NUM 		0x18
+#define PCI_BRIDGE_SEC_BUS_NUM 			0x19
+#define PCI_BRIDGE_SUBORD_BUS_NUM 		0x1A
+#define PCI_BRIDGE_SEC_LATENCY_TIMER 	0x1B
+#define PCI_BRIDGE_IO_BASE 				0x1C
+#define PCI_BRIDGE_IO_LIMIT 			0x1D
+#define PCI_BRIDGE_SEC_STATUS 			0x1E
+#define PCI_BRIDGE_MEMORY_BASE			0x20
+#define PCI_BRIDGE_MEMORY_LIMIT			0x22
+#define PCI_BRIDGE_PREF_MEMORY_BASE		0x24
+#define PCI_BRIDGE_PREF_MEMORY_LIMIT	0x26
+#define PCI_BRIDGE_PREF_MEMORY_BASE_UP	0x28
+#define PCI_BRIDGE_PREF_MEMORY_LIMIT_UP	0x2C
+#define PCI_BRIDGE_IO_BASE_UP			0x30
+#define PCI_BRIDGE_IO_LIMIT_UP 			0x32
+#define PCI_BRIDGE_EXP_ROM_BASE			0x38
+#define PCI_BRIDGE_INT_LINE				0x3C
+#define PCI_BRIDGE_INT_PIN				0x3D
+#define PCI_BRIDGE_CTL					0x3E
+
+#endif
+
+
+/**
+ * @}
+ */
Index: uspace/srv/drivers/pciintel/pciintel.ma
===================================================================
--- uspace/srv/drivers/pciintel/pciintel.ma	(revision 04cb68f2d06da3440e206ec4339c4d23afa3910a)
+++ uspace/srv/drivers/pciintel/pciintel.ma	(revision 04cb68f2d06da3440e206ec4339c4d23afa3910a)
@@ -0,0 +1,1 @@
+10 intel_pci
Index: uspace/srv/drivers/root/Makefile
===================================================================
--- uspace/srv/drivers/root/Makefile	(revision 04cb68f2d06da3440e206ec4339c4d23afa3910a)
+++ uspace/srv/drivers/root/Makefile	(revision 04cb68f2d06da3440e206ec4339c4d23afa3910a)
@@ -0,0 +1,36 @@
+# Copyright (c) 2010 Lenka Trochtova
+# 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 = root
+
+SOURCES = \
+	root.c
+
+include $(USPACE_PREFIX)/Makefile.common
Index: uspace/srv/drivers/root/root.c
===================================================================
--- uspace/srv/drivers/root/root.c	(revision 04cb68f2d06da3440e206ec4339c4d23afa3910a)
+++ uspace/srv/drivers/root/root.c	(revision 04cb68f2d06da3440e206ec4339c4d23afa3910a)
@@ -0,0 +1,147 @@
+/*
+ * Copyright (c) 2010 Lenka Trochtova
+ * 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 root Root device driver.
+ * @brief HelenOS root device driver.
+ * @{
+ */
+
+/** @file
+ */
+
+#include <assert.h>
+#include <stdio.h>
+#include <errno.h>
+#include <bool.h>
+#include <fibril_synch.h>
+#include <stdlib.h>
+#include <str.h>
+#include <ctype.h>
+#include <macros.h>
+
+#include <driver.h>
+#include <devman.h>
+#include <ipc/devman.h>
+
+#define NAME "root"
+
+static int root_add_device(device_t *dev);
+
+/** The root device driver's standard operations.
+ */
+static driver_ops_t root_ops = {
+	.add_device = &root_add_device
+};
+
+/** The root device driver structure. 
+ */
+static driver_t root_driver = {
+	.name = NAME,
+	.driver_ops = &root_ops
+};
+
+/** Create the device which represents the root of HW device tree.
+ * 
+ * @param parent parent of the newly created device.
+ * @return 0 on success, negative error number otherwise.
+ */
+static int add_platform_child(device_t *parent) {
+	printf(NAME ": adding new child for platform device.\n");
+	
+	int res = EOK;
+	device_t *platform = NULL;
+	match_id_t *match_id = NULL;	
+	
+	// create new device
+	if (NULL == (platform = create_device())) {
+		res = ENOMEM;
+		goto failure;
+	}	
+	
+	platform->name = "hw";
+	printf(NAME ": the new device's name is %s.\n", platform->name);
+	
+	// initialize match id list
+	if (NULL == (match_id = create_match_id())) {
+		res = ENOMEM;
+		goto failure;
+	}
+	
+	// TODO - replace this with some better solution (sysinfo ?)
+	match_id->id = STRING(UARCH);
+	match_id->score = 100;
+	add_match_id(&platform->match_ids, match_id);	
+	
+	// register child  device
+	res = child_device_register(platform, parent);
+	if (EOK != res) {
+		goto failure;
+	}
+	
+	return res;
+	
+failure:
+	if (NULL != match_id) {
+		match_id->id = NULL;
+	}
+	
+	if (NULL != platform) {
+		platform->name = NULL;
+		delete_device(platform);		
+	}
+	
+	return res;	
+}
+
+/** Get the root device.
+ * @param dev the device which is root of the whole device tree (both of HW and pseudo devices).
+ */
+static int root_add_device(device_t *dev) 
+{
+	printf(NAME ": root_add_device, device handle = %d\n", dev->handle);
+	
+	// register root device's children	
+	int res = add_platform_child(dev);	
+	if (EOK != res) {
+		printf(NAME ": failed to add child device for platform.\n");
+	}
+	
+	return res;
+}
+
+int main(int argc, char *argv[])
+{
+	printf(NAME ": HelenOS root device driver\n");	
+	return driver_main(&root_driver);
+}
+
+/**
+ * @}
+ */
+ 
Index: uspace/srv/drivers/root/root.ma
===================================================================
--- uspace/srv/drivers/root/root.ma	(revision 04cb68f2d06da3440e206ec4339c4d23afa3910a)
+++ uspace/srv/drivers/root/root.ma	(revision 04cb68f2d06da3440e206ec4339c4d23afa3910a)
@@ -0,0 +1,1 @@
+10 root
Index: uspace/srv/drivers/rootia32/Makefile
===================================================================
--- uspace/srv/drivers/rootia32/Makefile	(revision 04cb68f2d06da3440e206ec4339c4d23afa3910a)
+++ uspace/srv/drivers/rootia32/Makefile	(revision 04cb68f2d06da3440e206ec4339c4d23afa3910a)
@@ -0,0 +1,36 @@
+# Copyright (c) 2010 Lenka Trochtova
+# 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 = rootia32
+
+SOURCES = \
+	rootia32.c
+
+include $(USPACE_PREFIX)/Makefile.common
Index: uspace/srv/drivers/rootia32/rootia32.c
===================================================================
--- uspace/srv/drivers/rootia32/rootia32.c	(revision 04cb68f2d06da3440e206ec4339c4d23afa3910a)
+++ uspace/srv/drivers/rootia32/rootia32.c	(revision 04cb68f2d06da3440e206ec4339c4d23afa3910a)
@@ -0,0 +1,203 @@
+/*
+ * Copyright (c) 2010 Lenka Trochtova
+ * 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 root_ia32 Root HW device driver for ia32 platform.
+ * @brief HelenOS root HW device driver for ia32 platform.
+ * @{
+ */
+
+/** @file
+ */
+
+#include <assert.h>
+#include <stdio.h>
+#include <errno.h>
+#include <bool.h>
+#include <fibril_synch.h>
+#include <stdlib.h>
+#include <str.h>
+#include <ctype.h>
+#include <macros.h>
+
+#include <driver.h>
+#include <devman.h>
+#include <ipc/devman.h>
+#include <ipc/dev_iface.h>
+#include <resource.h>
+#include <device/hw_res.h>
+
+#define NAME "rootia32"
+
+typedef struct rootia32_child_dev_data {
+	hw_resource_list_t hw_resources;	
+} rootia32_child_dev_data_t;
+
+static int rootia32_add_device(device_t *dev);
+static void root_ia32_init(void);
+
+/** The root device driver's standard operations.
+ */
+static driver_ops_t rootia32_ops = {
+	.add_device = &rootia32_add_device
+};
+
+/** The root device driver structure. 
+ */
+static driver_t rootia32_driver = {
+	.name = NAME,
+	.driver_ops = &rootia32_ops
+};
+
+static hw_resource_t pci_conf_regs = {
+	.type = IO_RANGE,
+	.res.io_range = {
+		.address = 0xCF8,
+		.size = 8,
+		.endianness = LITTLE_ENDIAN	
+	}	
+};
+
+static rootia32_child_dev_data_t pci_data = {
+	.hw_resources = {
+		1, 
+		&pci_conf_regs
+	}
+};
+
+static hw_resource_list_t * rootia32_get_child_resources(device_t *dev)
+{
+	rootia32_child_dev_data_t *data = (rootia32_child_dev_data_t *)dev->driver_data;
+	if (NULL == data) {
+		return NULL;
+	}
+	return &data->hw_resources;
+}
+
+static bool rootia32_enable_child_interrupt(device_t *dev) 
+{
+	// TODO
+	
+	return false;
+}
+
+static resource_iface_t child_res_iface = {
+	&rootia32_get_child_resources,
+	&rootia32_enable_child_interrupt	
+};
+
+// initialized in root_ia32_init() function
+static device_ops_t rootia32_child_ops;
+
+static bool rootia32_add_child(
+	device_t *parent, const char *name, const char *str_match_id, 
+	rootia32_child_dev_data_t *drv_data) 
+{
+	printf(NAME ": adding new child device '%s'.\n", name);
+	
+	device_t *child = NULL;
+	match_id_t *match_id = NULL;	
+	
+	// create new device
+	if (NULL == (child = create_device())) {
+		goto failure;
+	}
+	
+	child->name = name;
+	child->driver_data = drv_data;
+	
+	// initialize match id list
+	if (NULL == (match_id = create_match_id())) {
+		goto failure;
+	}
+	match_id->id = str_match_id;
+	match_id->score = 100;
+	add_match_id(&child->match_ids, match_id);	
+	
+	// set provided operations to the device
+	child->ops = &rootia32_child_ops;
+	
+	// register child  device
+	if (EOK != child_device_register(child, parent)) {
+		goto failure;
+	}
+	
+	return true;
+	
+failure:
+	if (NULL != match_id) {
+		match_id->id = NULL;
+	}
+	
+	if (NULL != child) {
+		child->name = NULL;
+		delete_device(child);		
+	}
+	
+	printf(NAME ": failed to add child device '%s'.\n", name);
+	
+	return false;	
+}
+
+static bool rootia32_add_children(device_t *dev) 
+{
+	return rootia32_add_child(dev, "pci0", "intel_pci", &pci_data);
+}
+
+/** Get the root device.
+ * 
+ * @param dev the device which is root of the whole device tree (both of HW and pseudo devices).
+ * @return 0 on success, negative error number otherwise.
+ */
+static int rootia32_add_device(device_t *dev) 
+{
+	printf(NAME ": rootia32_add_device, device handle = %d\n", dev->handle);
+	
+	// register child devices	
+	if (!rootia32_add_children(dev)) {
+		printf(NAME ": failed to add child devices for platform ia32.\n");
+	}
+	
+	return EOK;
+}
+
+static void root_ia32_init() {
+	rootia32_child_ops.interfaces[HW_RES_DEV_IFACE] = &child_res_iface;
+}
+
+int main(int argc, char *argv[])
+{
+	printf(NAME ": HelenOS rootia32 device driver\n");	
+	root_ia32_init();
+	return driver_main(&rootia32_driver);
+}
+
+/**
+ * @}
+ */
+ 
Index: uspace/srv/drivers/rootia32/rootia32.ma
===================================================================
--- uspace/srv/drivers/rootia32/rootia32.ma	(revision 04cb68f2d06da3440e206ec4339c4d23afa3910a)
+++ uspace/srv/drivers/rootia32/rootia32.ma	(revision 04cb68f2d06da3440e206ec4339c4d23afa3910a)
@@ -0,0 +1,1 @@
+10 ia32
