--- ztdummy.c	2007-01-25 10:04:46.000000000 +0100
+++ /home/karsten/src/zaptel-1.2.12/ztdummy.c	2007-01-25 09:31:47.000000000 +0100
@@ -95,6 +95,9 @@
 
 static int debug = 0;
 
+/* interrupt from extern module in use? */
+static int use_extern_interrupt = 0;
+
 #ifdef LINUX26
 #ifndef USE_RTC
 /* New 2.6 kernel timer stuff */
@@ -125,6 +128,14 @@
 
 #endif
 
+/* extern interrupt - called at 1000Hz for example from mISDN kernel module hfc_multi */
+static void ztdummy_extern_interrupt(void)
+{
+	zt_receive(&ztd->span);
+	zt_transmit(&ztd->span);
+}
+EXPORT_SYMBOL_GPL(ztdummy_extern_interrupt);
+
 
 #ifdef LINUX26
 #ifdef USE_RTC
@@ -195,8 +206,33 @@
 	return 0;
 }
 
-int init_module(void)
+/* function to register the interrupt from external module
+ * nothing more to do than to cancel the other interrupt routines */
+static void ztdummy_register_interrupt(void)
 {
+	/* to avoid second unregistration of old interrupts */
+	if(!use_extern_interrupt) {
+		use_extern_interrupt = 1;
+#ifdef LINUX26
+#ifdef USE_RTC
+		rtc_control(&ztd->rtc_task, RTC_PIE_OFF, 0);
+		rtc_unregister(&ztd->rtc_task);
+#else
+		del_timer(&timer);
+#endif
+#else
+		free_irq(s->irq, ztd);  /* disable interrupts */
+#endif
+		printk("ztdummy: Using external time source.\n");
+	}
+}
+EXPORT_SYMBOL_GPL(ztdummy_register_interrupt);
+
+/* function to unregister the interrupt from external module
+ * reactivate formerly used routines */
+static int ztdummy_unregister_interrupt(void)
+{
+
 #ifdef LINUX26
 #ifdef USE_RTC
 	int err;
@@ -208,39 +244,9 @@
 #else
 	spinlock_t mylock = SPIN_LOCK_UNLOCKED;
 #endif
-
-	if (uhci_devices==NULL){
-		printk ("ztdummy: Uhci_devices pointer error.\n");
-		return -ENODEV;
-	}
-	s=*uhci_devices;     /* uhci device */
-	if (s==NULL){
-		printk ("ztdummy: No uhci_device found.\n");
-		return -ENODEV;
-	}
 #endif
 
-#if defined(LINUX26) && !defined(USE_RTC)
-	if (HZ != 1000) {
-		printk("ztdummy: This module requires the kernel HZ setting to be 1000 ticks per second\n");
-		return -ENODEV;
-	}
-#endif /* defined(LINUX26) && !defined(USE_RTC) */
-
-	ztd = kmalloc(sizeof(struct ztdummy), GFP_KERNEL);
-	if (ztd == NULL) {
-		printk("ztdummy: Unable to allocate memory\n");
-		return -ENOMEM;
-	}
-
-	memset(ztd, 0x0, sizeof(struct ztdummy));
-
-	if (ztdummy_initialize(ztd)) {
-		printk("ztdummy: Unable to intialize zaptel driver\n");
-		kfree(ztd);
-		return -ENODEV;
-	}
-
+	use_extern_interrupt = 0;
 #ifdef LINUX26
 #ifdef USE_RTC
 	atomic_set(&ztd->ticks, 0);
@@ -281,6 +287,51 @@
 	fill_td(td, TD_CTRL_IOC, 0, 0);
 	insert_td_horizontal(s, s->int_chain[0], td);	/* use int_chain[0] to get 1ms interrupts */
 #endif	
+	printk("ztdummy: Using internal time source\n");
+	return 0;
+}
+EXPORT_SYMBOL_GPL(ztdummy_unregister_interrupt);
+
+int init_module(void)
+{
+	int err;
+
+#ifndef LINUX26
+	if (uhci_devices==NULL){
+		printk ("ztdummy: Uhci_devices pointer error.\n");
+		return -ENODEV;
+	}
+	s=*uhci_devices;     /* uhci device */
+	if (s==NULL){
+		printk ("ztdummy: No uhci_device found.\n");
+		return -ENODEV;
+	}
+#endif
+
+#if defined(LINUX26) && !defined(USE_RTC)
+	if (HZ != 1000) {
+		printk("ztdummy: This module requires the kernel HZ setting to be 1000 ticks per second\n");
+		return -ENODEV;
+	}
+#endif /* defined(LINUX26) && !defined(USE_RTC) */
+
+	ztd = kmalloc(sizeof(struct ztdummy), GFP_KERNEL);
+	if (ztd == NULL) {
+		printk("ztdummy: Unable to allocate memory\n");
+		return -ENOMEM;
+	}
+
+	memset(ztd, 0x0, sizeof(struct ztdummy));
+
+	if (ztdummy_initialize(ztd)) {
+		printk("ztdummy: Unable to intialize zaptel driver\n");
+		kfree(ztd);
+		return -ENODEV;
+	}
+
+	/* unregister external interrupt means activate internal routines */
+	err = ztdummy_unregister_interrupt();
+	if (err) return err;
 
 	if (debug)
 		printk("ztdummy: init() finished\n");
@@ -290,16 +341,19 @@
 
 void cleanup_module(void)
 {
+	/* interrupts already disabled? */
+	if (use_extern_interrupt==0) {
 #ifdef LINUX26
 #ifdef USE_RTC
-	rtc_control(&ztd->rtc_task, RTC_PIE_OFF, 0);
-	rtc_unregister(&ztd->rtc_task);
+		rtc_control(&ztd->rtc_task, RTC_PIE_OFF, 0);
+		rtc_unregister(&ztd->rtc_task);
 #else
-	del_timer(&timer);
+		del_timer(&timer);
 #endif
 #else
-	free_irq(s->irq, ztd);  /* disable interrupts */
+		free_irq(s->irq, ztd);  /* disable interrupts */
 #endif
+	}
 	zt_unregister(&ztd->span);
 	kfree(ztd);
 #ifndef LINUX26
