diff --git a/libirqhelp/irqhelp.c b/libirqhelp/irqhelp.c
new file mode 100644
index 000000000..bafae6cf1
--- /dev/null
+++ b/libirqhelp/irqhelp.c
+void *
+irqhelp_server_loop(void *arg)
+{
+ struct irq *irq = (struct irq *)arg;
+
+ if (!irq)
+ {
+ printf("irqhelp cannot start this irq thread\n");
+ return NULL;
+ }
+
+ int interrupt_demuxer (mach_msg_header_t *inp,
+ mach_msg_header_t *outp)
+ {
+ device_intr_notification_t *n = (device_intr_notification_t *) inp;
+
+ ((mig_reply_header_t *) outp)->RetCode = MIG_NO_REPLY;
+ if (n->intr_header.msgh_id != DEVICE_INTR_NOTIFY)
+ return 0; /* not an interrupt */
+
+ /* FIXME: id <-> gsi now has an indirection, assuming 1:1 */
+ if (n->id != irq->gsi)
+ return 0; /* interrupt not for us */
+
+ /* wait if irq disabled */
+ pthread_mutex_lock (&irq->irqlock);
+ while (!irq->enabled)
+ pthread_cond_wait (&irq->irqcond, &irq->irqlock);
+ pthread_mutex_unlock (&irq->irqlock); > +
+ /* call handler */
+ irq->handler(irq->context);
+
+ /* ACK interrupt */
+ device_intr_ack (irqdev, irq->port, MACH_MSG_TYPE_MAKE_SEND);
+
+ if (irq->shutdown)
+ {
+ mach_port_deallocate(mach_task_self (), irq->port);
+ irq->port = MACH_PORT_NULL;
+ pthread_cond_destroy(&irq->irqcond);
+ pthread_mutex_destroy(&irq->irqlock);
+ free(irq);
+ pthread_exit(NULL);