Index: kernel/generic/src/ddi/irq.c
===================================================================
--- kernel/generic/src/ddi/irq.c	(revision 9979acb60a5eb42e08938818e5cc4fd945626555)
+++ kernel/generic/src/ddi/irq.c	(revision 1e23e1606ce0db1b69b7ef358deb4ae88ea16f0b)
@@ -70,6 +70,8 @@
 #include <ddi/irq.h>
 #include <adt/hash_table.h>
+#include <mm/slab.h>
 #include <arch/types.h>
 #include <synch/spinlock.h>
+#include <memstr.h>
 #include <arch.h>
 
@@ -78,9 +80,18 @@
 
 /**
- * Spinlock protecting the hash table.
+ * Spinlock protecting the kernel IRQ hash table.
  * This lock must be taken only when interrupts are disabled.
  */
-SPINLOCK_INITIALIZE(irq_hash_table_lock);
-static hash_table_t irq_hash_table;
+static SPINLOCK_INITIALIZE(irq_kernel_hash_table_lock);
+/** The kernel IRQ hash table. */
+static hash_table_t irq_kernel_hash_table;
+
+/**
+ * Spinlock protecting the uspace IRQ hash table.
+ * This lock must be taken only when interrupts are disabled.
+ */
+SPINLOCK_INITIALIZE(irq_uspace_hash_table_lock);
+/** The uspace IRQ hash table. */
+hash_table_t irq_uspace_hash_table;
 
 /**
@@ -112,4 +123,7 @@
 };
 
+/** Number of buckets in either of the hash tables. */
+static count_t buckets;
+
 /** Initialize IRQ subsystem.
  *
@@ -119,4 +133,5 @@
 void irq_init(count_t inrs, count_t chains)
 {
+	buckets = chains;
 	/*
 	 * Be smart about the choice of the hash table operations.
@@ -125,8 +140,15 @@
 	 * different keys), we can use optimized set of operations.
 	 */
-	if (inrs == chains)
-		hash_table_create(&irq_hash_table, chains, 2, &irq_lin_ops);
-	else
-		hash_table_create(&irq_hash_table, chains, 2, &irq_ht_ops);
+	if (inrs == chains) {
+		hash_table_create(&irq_uspace_hash_table, chains, 2,
+		    &irq_lin_ops);
+		hash_table_create(&irq_kernel_hash_table, chains, 2,
+		    &irq_lin_ops);
+	} else {
+		hash_table_create(&irq_uspace_hash_table, chains, 2,
+		    &irq_ht_ops);
+		hash_table_create(&irq_kernel_hash_table, chains, 2,
+		    &irq_ht_ops);
+	}
 }
 
@@ -138,21 +160,10 @@
 void irq_initialize(irq_t *irq)
 {
+	memsetb(irq, 0, sizeof(irq_t));
 	link_initialize(&irq->link);
 	spinlock_initialize(&irq->lock, "irq.lock");
-	irq->preack = false;
+	link_initialize(&irq->notif_cfg.link);
 	irq->inr = -1;
 	irq->devno = -1;
-	irq->trigger = (irq_trigger_t) 0;
-	irq->claim = NULL;
-	irq->handler = NULL;
-	irq->instance = NULL;
-	irq->cir = NULL;
-	irq->cir_arg = NULL;
-	irq->notif_cfg.notify = false;
-	irq->notif_cfg.answerbox = NULL;
-	irq->notif_cfg.code = NULL;
-	irq->notif_cfg.method = 0;
-	irq->notif_cfg.counter = 0;
-	link_initialize(&irq->notif_cfg.link);
 }
 
@@ -161,10 +172,13 @@
  * The irq structure must be filled with information
  * about the interrupt source and with the claim()
- * function pointer and irq_handler() function pointer.
- *
- * @param irq IRQ structure belonging to a device.
+ * function pointer and handler() function pointer.
+ *
+ * @param irq		IRQ structure belonging to a device.
+ * @return		True on success, false on failure.
  */
 void irq_register(irq_t *irq)
 {
+	spinlock_t *lock = &irq_kernel_hash_table_lock;
+	hash_table_t *table = &irq_kernel_hash_table;
 	ipl_t ipl;
 	unative_t key[] = {
@@ -174,7 +188,9 @@
 	
 	ipl = interrupts_disable();
-	spinlock_lock(&irq_hash_table_lock);
-	hash_table_insert(&irq_hash_table, key, &irq->link);
-	spinlock_unlock(&irq_hash_table_lock);
+	spinlock_lock(lock);
+	spinlock_lock(&irq->lock);
+	hash_table_insert(table, key, &irq->link);
+	spinlock_unlock(&irq->lock);	
+	spinlock_unlock(lock);
 	interrupts_restore(ipl);
 }
@@ -202,56 +218,31 @@
 	};
 	
-	spinlock_lock(&irq_hash_table_lock);
-
-	lnk = hash_table_find(&irq_hash_table, key);
+	/*
+	 * Try uspace handlers first.
+	 */
+	spinlock_lock(&irq_uspace_hash_table_lock);
+	lnk = hash_table_find(&irq_uspace_hash_table, key);
 	if (lnk) {
 		irq_t *irq;
 		
 		irq = hash_table_get_instance(lnk, irq_t, link);
-
-		spinlock_unlock(&irq_hash_table_lock);
+		spinlock_unlock(&irq_uspace_hash_table_lock);
 		return irq;
 	}
-	
-	spinlock_unlock(&irq_hash_table_lock);
-
-	return NULL;	
-}
-
-/** Find the IRQ structure corresponding to inr and devno.
- *
- * This functions attempts to lookup the IRQ structure
- * corresponding to its arguments. On success, this
- * function returns with interrups disabled, holding
- * the lock of the respective IRQ structure.
- *
- * This function assumes interrupts are already disabled.
- *
- * @param inr INR being looked up.
- * @param devno Devno being looked up.
- *
- * @return Locked IRQ structure on success or NULL on failure.
- */
-irq_t *irq_find_and_lock(inr_t inr, devno_t devno)
-{
-	link_t *lnk;
-	unative_t keys[] = {
-		(unative_t) inr,
-		(unative_t) devno
-	};
-	
-	spinlock_lock(&irq_hash_table_lock);
-
-	lnk = hash_table_find(&irq_hash_table, keys);
+	spinlock_unlock(&irq_uspace_hash_table_lock);
+
+	/*
+	 * Fallback to kernel handlers.
+	 */
+	spinlock_lock(&irq_kernel_hash_table_lock);
+	lnk = hash_table_find(&irq_kernel_hash_table, key);
 	if (lnk) {
 		irq_t *irq;
 		
 		irq = hash_table_get_instance(lnk, irq_t, link);
-
-		spinlock_unlock(&irq_hash_table_lock);
+		spinlock_unlock(&irq_kernel_hash_table_lock);
 		return irq;
 	}
-	
-	spinlock_unlock(&irq_hash_table_lock);
+	spinlock_unlock(&irq_kernel_hash_table_lock);
 
 	return NULL;	
@@ -274,5 +265,5 @@
 {
 	inr_t inr = (inr_t) key[KEY_INR];
-	return inr % irq_hash_table.entries;
+	return inr % buckets;
 }
 
@@ -309,5 +300,5 @@
 		/* Invoked by irq_dispatch_and_lock(). */
 		rv = ((irq->inr == inr) &&
-		    (irq->claim(irq->instance) == IRQ_ACCEPT));
+		    (irq->claim(irq) == IRQ_ACCEPT));
 	} else {
 		/* Invoked by irq_find_and_lock(). */
@@ -368,5 +359,5 @@
 	if (devno == -1) {
 		/* Invoked by irq_dispatch_and_lock() */
-		rv = (irq->claim(irq->instance) == IRQ_ACCEPT);
+		rv = (irq->claim(irq) == IRQ_ACCEPT);
 	} else {
 		/* Invoked by irq_find_and_lock() */
