Index: uspace/srv/dd/Makefile
===================================================================
--- uspace/srv/dd/Makefile	(revision fcbd1be0f221add9330a1d6c130818a501791166)
+++ uspace/srv/dd/Makefile	(revision fcbd1be0f221add9330a1d6c130818a501791166)
@@ -0,0 +1,92 @@
+#
+# Copyright (c) 2005 Martin Decky
+# 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.
+#
+
+## Setup toolchain
+#
+
+LIBC_PREFIX = ../../lib/libc
+SOFTINT_PREFIX = ../../lib/softint
+
+include $(LIBC_PREFIX)/Makefile.toolchain
+
+CFLAGS += -I../libipc/include
+
+LIBS =  $(LIBC_PREFIX)/libc.a
+
+## Sources
+#
+
+OUTPUT = pci
+SOURCES = \
+	main.c \
+	pic.c \
+	pci.c \
+	intel_piix3.c \
+	isa.c \
+	serial.c
+
+ifeq ($(PROCESSOR), us)
+	SOURCES += psycho.c
+endif
+
+ifeq ($(UARCH), ia32)
+	SOURCES += intel_method1.c
+endif
+
+CFLAGS += -D$(UARCH)
+
+OBJECTS := $(addsuffix .o,$(basename $(SOURCES)))
+
+.PHONY: all clean depend disasm
+
+all: $(OUTPUT) $(OUTPUT).disasm
+
+-include Makefile.depend
+
+clean:
+	-rm -f $(OUTPUT) $(OUTPUT).map $(OUTPUT).disasm Makefile.depend $(OBJECTS)
+
+depend:
+	$(CC) $(DEFS) $(CFLAGS) -M $(SOURCES) > Makefile.depend
+
+$(OUTPUT): $(OBJECTS) $(LIBS)
+	$(LD) -T $(LIBC_PREFIX)/arch/$(UARCH)/_link.ld $(OBJECTS) $(LIBS) $(LFLAGS) -o $@ -Map $(OUTPUT).map
+
+disasm: $(OUTPUT).disasm
+
+$(OUTPUT).disasm: $(OUTPUT)
+	$(OBJDUMP) -d $< >$@
+
+%.o: %.S
+	$(CC) $(DEFS) $(AFLAGS) $(CFLAGS) -D__ASM__ -c $< -o $@
+
+%.o: %.s
+	$(AS) $(AFLAGS) $< -o $@
+
+%.o: %.c
+	$(CC) $(DEFS) $(CFLAGS) -c $< -o $@
Index: uspace/srv/dd/intel_method1.c
===================================================================
--- uspace/srv/dd/intel_method1.c	(revision fcbd1be0f221add9330a1d6c130818a501791166)
+++ uspace/srv/dd/intel_method1.c	(revision fcbd1be0f221add9330a1d6c130818a501791166)
@@ -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 fcbd1be0f221add9330a1d6c130818a501791166)
+++ uspace/srv/dd/intel_piix3.c	(revision fcbd1be0f221add9330a1d6c130818a501791166)
@@ -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 fcbd1be0f221add9330a1d6c130818a501791166)
+++ uspace/srv/dd/intel_piix3.h	(revision fcbd1be0f221add9330a1d6c130818a501791166)
@@ -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 fcbd1be0f221add9330a1d6c130818a501791166)
+++ uspace/srv/dd/isa.c	(revision fcbd1be0f221add9330a1d6c130818a501791166)
@@ -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 fcbd1be0f221add9330a1d6c130818a501791166)
+++ uspace/srv/dd/isa.h	(revision fcbd1be0f221add9330a1d6c130818a501791166)
@@ -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 fcbd1be0f221add9330a1d6c130818a501791166)
+++ uspace/srv/dd/main.c	(revision fcbd1be0f221add9330a1d6c130818a501791166)
@@ -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 fcbd1be0f221add9330a1d6c130818a501791166)
+++ uspace/srv/dd/pci.c	(revision fcbd1be0f221add9330a1d6c130818a501791166)
@@ -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 fcbd1be0f221add9330a1d6c130818a501791166)
+++ uspace/srv/dd/pci.h	(revision fcbd1be0f221add9330a1d6c130818a501791166)
@@ -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 fcbd1be0f221add9330a1d6c130818a501791166)
+++ uspace/srv/dd/pci_bus.h	(revision fcbd1be0f221add9330a1d6c130818a501791166)
@@ -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 fcbd1be0f221add9330a1d6c130818a501791166)
+++ uspace/srv/dd/pci_conf.h	(revision fcbd1be0f221add9330a1d6c130818a501791166)
@@ -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 fcbd1be0f221add9330a1d6c130818a501791166)
+++ uspace/srv/dd/pci_regs.h	(revision fcbd1be0f221add9330a1d6c130818a501791166)
@@ -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 fcbd1be0f221add9330a1d6c130818a501791166)
+++ uspace/srv/dd/pic.c	(revision fcbd1be0f221add9330a1d6c130818a501791166)
@@ -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 fcbd1be0f221add9330a1d6c130818a501791166)
+++ uspace/srv/dd/pic.h	(revision fcbd1be0f221add9330a1d6c130818a501791166)
@@ -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 fcbd1be0f221add9330a1d6c130818a501791166)
+++ uspace/srv/dd/psycho.c	(revision fcbd1be0f221add9330a1d6c130818a501791166)
@@ -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 fcbd1be0f221add9330a1d6c130818a501791166)
+++ uspace/srv/dd/serial.c	(revision fcbd1be0f221add9330a1d6c130818a501791166)
@@ -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 fcbd1be0f221add9330a1d6c130818a501791166)
+++ uspace/srv/dd/serial.h	(revision fcbd1be0f221add9330a1d6c130818a501791166)
@@ -0,0 +1,8 @@
+#ifndef SERIAL_H
+#define SERIAL_H
+
+int serial_init();
+
+
+#endif
+
