Index: uspace/drv/char/i8042/buffer.h
===================================================================
--- uspace/drv/char/i8042/buffer.h	(revision 9f97ffe752958b32a83323bffa5931d4b417c42a)
+++ uspace/drv/char/i8042/buffer.h	(revision 9f97ffe752958b32a83323bffa5931d4b417c42a)
@@ -0,0 +1,117 @@
+/*
+ * Copyright (c) 2011 Jan Vesely
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+/** @addtogroup kbd_port
+ * @ingroup  kbd
+ * @{
+ */
+/** @file
+ * @brief i8042 port driver.
+ */
+
+#ifndef BUFFER_H_
+#define BUFFER_H_
+
+#include <assert.h>
+#include <fibril_synch.h>
+
+typedef struct {
+	uint8_t *buffer;
+	uint8_t *buffer_end;
+	fibril_mutex_t guard;
+	fibril_condvar_t change;
+	uint8_t *read_head;
+	uint8_t *write_head;
+} buffer_t;
+
+static inline void buffer_init(buffer_t *buffer, uint8_t *data, size_t size)
+{
+	assert(buffer);
+	fibril_mutex_initialize(&buffer->guard);
+	fibril_condvar_initialize(&buffer->change);
+	buffer->buffer = data;
+	buffer->buffer_end = data + size;
+	buffer->read_head = buffer->buffer;
+	buffer->write_head = buffer->buffer;
+	bzero(buffer->buffer, size);
+}
+
+static inline void buffer_write(buffer_t *buffer, uint8_t data)
+{
+	fibril_mutex_lock(&buffer->guard);
+	/* Next position. */
+	uint8_t *new_head = buffer->write_head + 1;
+	if (new_head == buffer->buffer_end)
+		new_head = buffer->buffer;
+	/* Buffer full. */
+	while (new_head == buffer->read_head)
+		fibril_condvar_wait(&buffer->change, &buffer->guard);
+	/* Write data. */
+	*buffer->write_head = data;
+
+	/* Buffer was empty. */
+	if (buffer->write_head == buffer->read_head)
+		fibril_condvar_broadcast(&buffer->change);
+
+	/* Move head */
+	buffer->write_head = new_head;
+	fibril_mutex_unlock(&buffer->guard);
+}
+
+static inline uint8_t buffer_read(buffer_t *buffer)
+{
+	fibril_mutex_lock(&buffer->guard);
+	/* Buffer is empty. */
+	while (buffer->write_head == buffer->read_head)
+		fibril_condvar_wait(&buffer->change, &buffer->guard);
+
+	/* Next position. */
+	uint8_t *new_head = buffer->read_head + 1;
+	if (new_head == buffer->buffer_end)
+		new_head = buffer->buffer;
+
+	/* Read data. */
+	const uint8_t data = *buffer->read_head;
+
+	/* Buffer was full. */
+	uint8_t *new_write_head = buffer->write_head + 1;
+	if (new_write_head == buffer->buffer_end)
+		new_write_head = buffer->buffer;
+	while (new_write_head == buffer->read_head)
+		fibril_condvar_broadcast(&buffer->change);
+	/* Move head */
+	buffer->read_head = new_head;
+
+	fibril_mutex_unlock(&buffer->guard);
+	return data;
+}
+
+
+#endif
+/**
+ * @}
+ */
Index: uspace/drv/char/i8042/i8042.c
===================================================================
--- uspace/drv/char/i8042/i8042.c	(revision c6c5ff3b46c0cf4ba85b55c1e816e8e602fa609c)
+++ uspace/drv/char/i8042/i8042.c	(revision 9f97ffe752958b32a83323bffa5931d4b417c42a)
@@ -142,9 +142,12 @@
 		return;
 	i8042_t *controller = dev->driver_data;
-	fibril_mutex_lock(&controller->guard);
+//	fibril_mutex_lock(&controller->guard);
 
 	const uint8_t status = IPC_GET_ARG1(*call);
 	const uint8_t data = IPC_GET_ARG2(*call);
-	const bool aux = (status & i8042_AUX_DATA);
+	buffer_t *buffer = (status & i8042_AUX_DATA) ?
+	    &controller->aux_buffer : &controller->kbd_buffer;
+	buffer_write(buffer, data);
+#if 0
 	char ** buffer =
 	    aux ? &controller->aux_buffer : &controller->kbd_buffer;
@@ -162,4 +165,5 @@
 
 	fibril_mutex_unlock(&controller->guard);
+#endif
 }
 /*----------------------------------------------------------------------------*/
@@ -203,10 +207,7 @@
 	dev->mouse_fun->driver_data = dev;
 
-	fibril_mutex_initialize(&dev->guard);
-	fibril_condvar_initialize(&dev->data_avail);
-	dev->kbd_buffer = NULL;
-	dev->kbd_buffer_end = NULL;
-	dev->aux_buffer = NULL;
-	dev->aux_buffer_end = NULL;
+	buffer_init(&dev->kbd_buffer, dev->kbd_data, BUFFER_SIZE);
+	buffer_init(&dev->aux_buffer, dev->aux_data, BUFFER_SIZE);
+	fibril_mutex_initialize(&dev->write_guard);
 
 #define CHECK_RET_DESTROY(ret, msg...) \
@@ -300,10 +301,10 @@
 	assert(fun->driver_data);
 	i8042_t *controller = fun->driver_data;
-	fibril_mutex_lock(&controller->guard);
+	fibril_mutex_lock(&controller->write_guard);
 	for (size_t i = 0; i < size; ++i) {
 		wait_ready_write(controller);
 		pio_write_8(&controller->regs->data, buffer[i]);
 	}
-	fibril_mutex_unlock(&controller->guard);
+	fibril_mutex_unlock(&controller->write_guard);
 	return size;
 }
@@ -316,21 +317,8 @@
 
 	i8042_t *controller = fun->driver_data;
-	fibril_mutex_lock(&controller->guard);
-	/* There is someone else reading from the device. */
-	if (controller->kbd_buffer) {
-		fibril_mutex_unlock(&controller->guard);
-		return EBUSY;
-	}
-	controller->kbd_buffer = buffer;
-	controller->kbd_buffer_end = buffer + size;
-
-	/* Wait for buffer to be filled */
-	while (controller->kbd_buffer != controller->kbd_buffer_end)
-		fibril_condvar_wait(
-		    &controller->data_avail, &controller->guard);
-
-	controller->kbd_buffer = NULL;
-	controller->kbd_buffer_end = NULL;
-	fibril_mutex_unlock(&controller->guard);
+
+	for (size_t i = 0; i < size; ++i) {
+		*buffer++ = buffer_read(&controller->kbd_buffer);
+	}
 	return size;
 }
@@ -341,5 +329,5 @@
 	assert(fun->driver_data);
 	i8042_t *controller = fun->driver_data;
-	fibril_mutex_lock(&controller->guard);
+	fibril_mutex_lock(&controller->write_guard);
 	for (size_t i = 0; i < size; ++i) {
 		wait_ready_write(controller);
@@ -347,5 +335,5 @@
 		pio_write_8(&controller->regs->data, buffer[i]);
 	}
-	fibril_mutex_unlock(&controller->guard);
+	fibril_mutex_unlock(&controller->write_guard);
 	return size;
 }
@@ -358,21 +346,7 @@
 
 	i8042_t *controller = fun->driver_data;
-	fibril_mutex_lock(&controller->guard);
-	/* There is someone else reading from the device. */
-	if (controller->aux_buffer) {
-		fibril_mutex_unlock(&controller->guard);
-		return EBUSY;
-	}
-	controller->aux_buffer = buffer;
-	controller->aux_buffer_end = buffer + size;
-
-	/* Wait for buffer to be filled */
-	while (controller->aux_buffer != controller->aux_buffer_end)
-		fibril_condvar_wait(
-		    &controller->data_avail, &controller->guard);
-
-	controller->aux_buffer = NULL;
-	controller->aux_buffer_end = NULL;
-	fibril_mutex_unlock(&controller->guard);
+	for (size_t i = 0; i < size; ++i) {
+		*buffer++ = buffer_read(&controller->aux_buffer);
+	}
 	return size;
 }
Index: uspace/drv/char/i8042/i8042.h
===================================================================
--- uspace/drv/char/i8042/i8042.h	(revision c6c5ff3b46c0cf4ba85b55c1e816e8e602fa609c)
+++ uspace/drv/char/i8042/i8042.h	(revision 9f97ffe752958b32a83323bffa5931d4b417c42a)
@@ -1,4 +1,5 @@
 /*
  * Copyright (c) 2006 Josef Cejka
+ * Copyright (c) 2011 Jan Vesely
  * All rights reserved.
  *
@@ -26,10 +27,8 @@
  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
-
 /** @addtogroup kbd_port
  * @ingroup  kbd
  * @{
  */
-
 /** @file
  * @brief i8042 port driver.
@@ -45,4 +44,8 @@
 #include <ddf/driver.h>
 
+#include "buffer.h"
+
+#define BUFFER_SIZE 12
+
 /** i8042 HW I/O interface */
 typedef struct {
@@ -52,31 +55,15 @@
 } __attribute__ ((packed)) i8042_regs_t;
 
-/** Softstate structure, one for each serial port (primary and aux). */
-/*
-typedef struct {
-	service_id_t service_id;
-	async_sess_t *client_sess;
-} i8042_port_t;
-*/
-
 typedef struct i8042 i8042_t;
-
-enum {
-	DEVID_PRI = 0, /**< primary device */
-        DEVID_AUX = 1, /**< AUX device */
-	MAX_DEVS  = 2
-};
 
 struct i8042 {
 	i8042_regs_t *regs;
-//	i8042_port_t port[MAX_DEVS];
 	ddf_fun_t *kbd_fun;
 	ddf_fun_t *mouse_fun;
-	char * kbd_buffer;
-	char * kbd_buffer_end;
-	char * aux_buffer;
-	char * aux_buffer_end;
-	fibril_mutex_t guard;
-	fibril_condvar_t data_avail;
+	buffer_t aux_buffer;
+	buffer_t kbd_buffer;
+	uint8_t aux_data[BUFFER_SIZE];
+	uint8_t kbd_data[BUFFER_SIZE];
+	fibril_mutex_t write_guard;
 };
 
