Index: uspace/srv/drivers/serial/cyclic_buffer.h
===================================================================
--- uspace/srv/drivers/serial/cyclic_buffer.h	(revision 1f8657ba3cd157b3235cbbeed0318164d656239c)
+++ uspace/srv/drivers/serial/cyclic_buffer.h	(revision 1f8657ba3cd157b3235cbbeed0318164d656239c)
@@ -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 serial
+ * @{
+ */
+/** @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/serial/serial.c
===================================================================
--- uspace/srv/drivers/serial/serial.c	(revision f928a8ada5c2d6dc33c5de53976697d179627577)
+++ uspace/srv/drivers/serial/serial.c	(revision 1f8657ba3cd157b3235cbbeed0318164d656239c)
@@ -49,4 +49,6 @@
 #include <fcntl.h>
 #include <sys/stat.h>
+#include <ddi.h>
+#include <libarch/ddi.h>
 
 #include <driver.h>
@@ -57,10 +59,35 @@
 #include <device/hw_res.h>
 
+#include "cyclic_buffer.h"
+
 #define NAME "serial"
 
+#define REG_COUNT 7
+
 typedef struct serial_dev_data {
-		
+	bool client_connected;
+	int irq;
+	uint32_t io_addr;
+	ioport8_t *port;
+	cyclic_buffer_t input_buffer;
+	fibril_mutex_t mutex;		
 } serial_dev_data_t;
 
+static serial_dev_data_t * create_serial_dev_data()
+{
+	serial_dev_data_t *data = (serial_dev_data_t *)malloc(sizeof(serial_dev_data_t));
+	if (NULL != data) {
+		memset(data, 0, sizeof(serial_dev_data_t));
+		fibril_mutex_initialize(&data->mutex);
+	}
+	return data;	
+}
+
+static void delete_serial_dev_data(serial_dev_data_t *data) 
+{
+	if (NULL != data) {
+		free(data);
+	}
+}
 
 static device_class_t serial_dev_class;
@@ -81,9 +108,148 @@
 };
 
+static void serial_dev_cleanup(device_t *dev)
+{
+	if (NULL != dev->driver_data) {
+		delete_serial_dev_data((serial_dev_data_t*)dev->driver_data);	
+		dev->driver_data = NULL;
+	}
+	
+	if (dev->parent_phone > 0) {
+		ipc_hangup(dev->parent_phone);
+		dev->parent_phone = 0;
+	}	
+}
+
+static bool serial_pio_enable(device_t *dev)
+{
+	printf(NAME ": serial_pio_enable = %s\n", dev->name);
+	
+	serial_dev_data_t *data = (serial_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;
+}
+
+static bool serial_dev_probe(device_t *dev)
+{
+	printf(NAME ": serial_dev_probe dev = %s\n", dev->name);
+	
+	serial_dev_data_t *data = (serial_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;	
+}
+
+static bool serial_dev_initialize(device_t *dev)
+{
+	printf(NAME ": serial_dev_initialize dev = %s\n", dev->name);
+	
+	hw_resource_list_t hw_resources;
+	memset(&hw_resources, 0, sizeof(hw_resource_list_t));
+	
+	// allocate driver data for the device
+	serial_dev_data_t *data = create_serial_dev_data();	
+	if (NULL == data) {
+		return false;
+	}
+	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);
+		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);
+		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);
+				goto failed;
+			}
+			ioport = true;
+			printf(NAME ": the %s device was asigned i/o address = 0x%x.\n", dev->name, data->io_addr);
+			break;			
+		}
+	}
+	
+	if (!irq || !ioport) {
+		printf(NAME ": missing hw resource(s) for the device %s.\n", dev->name);
+		goto failed;
+	}		
+	
+	clean_hw_resource_list(&hw_resources);
+	return true;
+	
+failed:
+	serial_dev_cleanup(dev);	
+	clean_hw_resource_list(&hw_resources);	
+	return false;	
+}
+
 static bool serial_add_device(device_t *dev) 
 {
 	printf(NAME ": serial_add_device, device handle = %d\n", dev->handle);
 	
-	// TODO
+	if (!serial_dev_initialize(dev)) {
+		return false;
+	}
+	
+	if (!serial_pio_enable(dev)) {
+		serial_dev_cleanup(dev);
+		return false;
+	}
+	
+	if (!serial_dev_probe(dev)) {
+		serial_dev_cleanup(dev);
+		return false;
+	}	
+	
+	// TODO interrupt and serial port initialization (baud rate etc.)
 	
 	return true;
