Index: uspace/lib/drv/generic/driver.c
===================================================================
--- uspace/lib/drv/generic/driver.c	(revision 228e490270cec3d6a6de666f61839f0d9ed5f193)
+++ uspace/lib/drv/generic/driver.c	(revision 5fdd7c393a9b587cf27839af315e5f0442583173)
@@ -52,17 +52,15 @@
 #include <ipc/driver.h>
 
+#include "dev_iface.h"
 #include "driver.h"
 
-/* driver structure */
-
+/** Driver structure */
 static driver_t *driver;
 
-/* devices */
-
+/** Devices */
 LIST_INITIALIZE(devices);
 FIBRIL_MUTEX_INITIALIZE(devices_mutex);
 
-/* interrupts */
-
+/** Interrupts */
 static interrupt_context_list_t interrupt_contexts;
 
@@ -85,7 +83,91 @@
 	
 	ctx = find_interrupt_context_by_id(&interrupt_contexts, id);
-	if (NULL != ctx && NULL != ctx->handler)
+	if (ctx != NULL && ctx->handler != NULL)
 		(*ctx->handler)(ctx->dev, iid, icall);
 }
+
+interrupt_context_t *create_interrupt_context(void)
+{
+	interrupt_context_t *ctx;
+	
+	ctx = (interrupt_context_t *) malloc(sizeof(interrupt_context_t));
+	if (ctx != NULL)
+		memset(ctx, 0, sizeof(interrupt_context_t));
+	
+	return ctx;
+}
+
+void delete_interrupt_context(interrupt_context_t *ctx)
+{
+	if (ctx != NULL)
+		free(ctx);
+}
+
+void init_interrupt_context_list(interrupt_context_list_t *list)
+{
+	memset(list, 0, sizeof(interrupt_context_list_t));
+	fibril_mutex_initialize(&list->mutex);
+	list_initialize(&list->contexts);
+}
+
+void
+add_interrupt_context(interrupt_context_list_t *list, interrupt_context_t *ctx)
+{
+	fibril_mutex_lock(&list->mutex);
+	ctx->id = list->curr_id++;
+	list_append(&ctx->link, &list->contexts);
+	fibril_mutex_unlock(&list->mutex);
+}
+
+void remove_interrupt_context(interrupt_context_list_t *list,
+    interrupt_context_t *ctx)
+{
+	fibril_mutex_lock(&list->mutex);
+	list_remove(&ctx->link);
+	fibril_mutex_unlock(&list->mutex);
+}
+
+interrupt_context_t *
+find_interrupt_context_by_id(interrupt_context_list_t *list, int id)
+{
+	fibril_mutex_lock(&list->mutex);
+	
+	link_t *link = list->contexts.next;
+	interrupt_context_t *ctx;
+	
+	while (link != &list->contexts) {
+		ctx = list_get_instance(link, interrupt_context_t, link);
+		if (ctx->id == id) {
+			fibril_mutex_unlock(&list->mutex);
+			return ctx;
+		}
+		link = link->next;
+	}
+	
+	fibril_mutex_unlock(&list->mutex);
+	return NULL;
+}
+
+interrupt_context_t *
+find_interrupt_context(interrupt_context_list_t *list, device_t *dev, int irq)
+{
+	fibril_mutex_lock(&list->mutex);
+	
+	link_t *link = list->contexts.next;
+	interrupt_context_t *ctx;
+	
+	while (link != &list->contexts) {
+		ctx = list_get_instance(link, interrupt_context_t, link);
+		if (ctx->irq == irq && ctx->dev == dev) {
+			fibril_mutex_unlock(&list->mutex);
+			return ctx;
+		}
+		link = link->next;
+	}
+	
+	fibril_mutex_unlock(&list->mutex);
+	return NULL;
+}
+
 
 int
@@ -101,9 +183,9 @@
 	add_interrupt_context(&interrupt_contexts, ctx);
 	
-	if (NULL == pseudocode)
+	if (pseudocode == NULL)
 		pseudocode = &default_pseudocode;
 	
 	int res = ipc_register_irq(irq, dev->handle, ctx->id, pseudocode);
-	if (0 != res) {
+	if (res != EOK) {
 		remove_interrupt_context(&interrupt_contexts, ctx);
 		delete_interrupt_context(ctx);
@@ -118,9 +200,10 @@
 	    dev, irq);
 	int res = ipc_unregister_irq(irq, dev->handle);
-
-	if (NULL != ctx) {
+	
+	if (ctx != NULL) {
 		remove_interrupt_context(&interrupt_contexts, ctx);
 		delete_interrupt_context(ctx);
 	}
+	
 	return res;
 }
@@ -140,5 +223,5 @@
 }
 
-static device_t * driver_get_device(link_t *devices, devman_handle_t handle)
+static device_t *driver_get_device(link_t *devices, devman_handle_t handle)
 {
 	device_t *dev = NULL;
@@ -146,7 +229,8 @@
 	fibril_mutex_lock(&devices_mutex);
 	link_t *link = devices->next;
+	
 	while (link != devices) {
 		dev = list_get_instance(link, device_t, link);
-		if (handle == dev->handle) {
+		if (dev->handle == handle) {
 			fibril_mutex_unlock(&devices_mutex);
 			return dev;
@@ -154,6 +238,7 @@
 		link = link->next;
 	}
+	
 	fibril_mutex_unlock(&devices_mutex);
-
+	
 	return NULL;
 }
@@ -162,9 +247,9 @@
 {
 	char *dev_name = NULL;
-	int res = EOK;
-	
-	devman_handle_t dev_handle =  IPC_GET_ARG1(*icall);
+	int res;
+	
+	devman_handle_t dev_handle = IPC_GET_ARG1(*icall);
     	devman_handle_t parent_dev_handle = IPC_GET_ARG2(*icall);
-    
+	
 	device_t *dev = create_device();
 	dev->handle = dev_handle;
@@ -177,5 +262,5 @@
 	
 	res = driver->driver_ops->add_device(dev);
-	if (0 == res) {
+	if (res == EOK) {
 		printf("%s: new device with handle=%" PRIun " was added.\n",
 		    driver->name, dev_handle);
@@ -194,10 +279,10 @@
 	/* 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_IMETHOD(call)) {
 		case IPC_M_PHONE_HUNGUP:
@@ -240,14 +325,14 @@
 	 * use the device.
 	 */
-
+	
 	int ret = EOK;
 	/* open the device */
-	if (NULL != dev->ops && NULL != dev->ops->open)
+	if (dev->ops != NULL && dev->ops->open != NULL)
 		ret = (*dev->ops->open)(dev);
 	
-	ipc_answer_0(iid, ret);	
-	if (EOK != ret)
+	ipc_answer_0(iid, ret);
+	if (ret != EOK)
 		return;
-
+	
 	while (1) {
 		ipc_callid_t callid;
@@ -258,11 +343,11 @@
 		
 		switch  (method) {
-		case IPC_M_PHONE_HUNGUP:		
+		case IPC_M_PHONE_HUNGUP:
 			/* close the device */
-			if (NULL != dev->ops && NULL != dev->ops->close)
+			if (dev->ops != NULL && dev->ops->close != NULL)
 				(*dev->ops->close)(dev);
 			ipc_answer_0(callid, EOK);
 			return;
-		default:		
+		default:
 			/* convert ipc interface id to interface index */
 			
@@ -272,5 +357,5 @@
 				remote_handler_t *default_handler =
 				    device_get_default_handler(dev);
-				if (NULL != default_handler) {
+				if (default_handler != NULL) {
 					(*default_handler)(dev, callid, &call);
 					break;
@@ -286,10 +371,10 @@
 				break;
 			}
-
+			
 			/* calling one of the device's interfaces */
 			
-			/* get the device interface structure */
-			void *iface = device_get_iface(dev, iface_idx);
-			if (NULL == iface) {
+			/* Get the interface ops structure. */
+			void *ops = device_get_ops(dev, iface_idx);
+			if (ops == NULL) {
 				printf("%s: driver_connection_gen error - ",
 				    driver->name);
@@ -299,17 +384,17 @@
 				break;
 			}
-
+			
 			/*
 			 * Get the corresponding interface for remote request
 			 * handling ("remote interface").
 			 */
-			remote_iface_t* rem_iface = get_remote_iface(iface_idx);
-			assert(NULL != rem_iface);
-
+			remote_iface_t *rem_iface = get_remote_iface(iface_idx);
+			assert(rem_iface != NULL);
+			
 			/* get the method of the remote interface */
 			sysarg_t iface_method_idx = IPC_GET_ARG1(call);
 			remote_iface_func_ptr_t iface_method_ptr =
 			    get_remote_method(rem_iface, iface_method_idx);
-			if (NULL == iface_method_ptr) {
+			if (iface_method_ptr == NULL) {
 				// the interface has not such method
 				printf("%s: driver_connection_gen error - "
@@ -325,5 +410,5 @@
 			 * associated with the device by its driver.
 			 */
-			(*iface_method_ptr)(dev, iface, callid, &call);
+			(*iface_method_ptr)(dev, ops, callid, &call);
 			break;
 		}
@@ -348,16 +433,15 @@
 	switch ((sysarg_t) (IPC_GET_ARG1(*icall))) {
 	case DRIVER_DEVMAN:
-		/* handle PnP events from device manager */
+		/* Handle request from device manager */
 		driver_connection_devman(iid, icall);
 		break;
 	case DRIVER_DRIVER:
-		/* handle request from drivers of child devices */
+		/* Handle request from drivers of child devices */
 		driver_connection_driver(iid, icall);
 		break;
 	case DRIVER_CLIENT:
-		/* handle requests from client applications */
+		/* Handle request from client applications */
 		driver_connection_client(iid, icall);
 		break;
-
 	default:
 		/* No such interface */
@@ -366,8 +450,44 @@
 }
 
+/** Create new device structure.
+ *
+ * @return		The device structure.
+ */
+device_t *create_device(void)
+{
+	device_t *dev = malloc(sizeof(device_t));
+
+	if (dev != NULL) {
+		memset(dev, 0, sizeof(device_t));
+		init_match_ids(&dev->match_ids);
+	}
+
+	return dev;
+}
+
+/** Delete device structure.
+ *
+ * @param dev		The device structure.
+ */
+void delete_device(device_t *dev)
+{
+	clean_match_ids(&dev->match_ids);
+	if (dev->name != NULL)
+		free(dev->name);
+	free(dev);
+}
+
+void *device_get_ops(device_t *dev, dev_inferface_idx_t idx)
+{
+	assert(is_valid_iface_idx(idx));
+	if (dev->ops == NULL)
+		return NULL;
+	return dev->ops->interfaces[idx];
+}
+
 int child_device_register(device_t *child, device_t *parent)
 {
-	assert(NULL != child->name);
-
+	assert(child->name != NULL);
+	
 	int res;
 	
@@ -375,7 +495,9 @@
 	res = devman_child_device_register(child->name, &child->match_ids,
 	    parent->handle, &child->handle);
-	if (EOK == res)
+	if (res != EOK) {
+		remove_from_devices_list(child);
 		return res;
-	remove_from_devices_list(child);	
+	}
+	
 	return res;
 }
@@ -395,5 +517,5 @@
 	match_id_t *match_id = NULL;
 	int rc;
-
+	
 	child = create_device();
 	if (child == NULL) {
@@ -401,7 +523,7 @@
 		goto failure;
 	}
-
+	
 	child->name = child_name;
-
+	
 	match_id = create_match_id();
 	if (match_id == NULL) {
@@ -409,15 +531,15 @@
 		goto failure;
 	}
-
+	
 	match_id->id = child_match_id;
 	match_id->score = child_match_score;
 	add_match_id(&child->match_ids, match_id);
-
+	
 	rc = child_device_register(child, parent);
-	if (EOK != rc)
+	if (rc != EOK)
 		goto failure;
-
+	
 	return EOK;
-
+	
 failure:
 	if (match_id != NULL) {
@@ -425,11 +547,24 @@
 		delete_match_id(match_id);
 	}
-
+	
 	if (child != NULL) {
 		child->name = NULL;
 		delete_device(child);
 	}
-
+	
 	return rc;
+}
+
+/** Get default handler for client requests */
+remote_handler_t *device_get_default_handler(device_t *dev)
+{
+	if (dev->ops == NULL)
+		return NULL;
+	return dev->ops->default_handler;
+}
+
+int add_device_to_class(device_t *dev, const char *class_name)
+{
+	return devman_add_device_to_class(dev->handle, class_name);
 }
 
@@ -441,5 +576,5 @@
 	 */
 	driver = drv;
-
+	
 	/* Initialize the list of interrupt contexts. */
 	init_interrupt_context_list(&interrupt_contexts);
@@ -453,7 +588,7 @@
 	 */
 	devman_driver_register(driver->name, driver_connection);
-
+	
 	async_manager();
-
+	
 	/* Never reached. */
 	return 0;
