summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authormarkster <markster@5390a7c7-147a-4af0-8ec9-7488f05a26cb>2005-05-25 17:58:36 +0000
committermarkster <markster@5390a7c7-147a-4af0-8ec9-7488f05a26cb>2005-05-25 17:58:36 +0000
commit83147351eb0bbf5f17df47c6ab3d9cd2ae91f971 (patch)
treecc27f3401cda541d6d3d74e7d805ca499663d6f6
parent32ca18d789a89c3a41c706219dc02aa65c87939c (diff)
ztdummy fixes (bug #4301)
git-svn-id: http://svn.digium.com/svn/zaptel/trunk@655 5390a7c7-147a-4af0-8ec9-7488f05a26cb
-rwxr-xr-xztdummy.c64
1 files changed, 63 insertions, 1 deletions
diff --git a/ztdummy.c b/ztdummy.c
index 92a41d7..1631c45 100755
--- a/ztdummy.c
+++ b/ztdummy.c
@@ -6,6 +6,7 @@
* Written by Robert Pleh <robert.pleh@hermes.si>
* 2.6 version by Tony Hoyle
* Unified by Mark Spencer <markster@digium.com>
+ * Converted to use RTC on i386 by Tony Mountifield <tony@softins.co.uk>
*
* Copyright (C) 2002, Hermes Softlab
* Copyright (C) 2004, Digium, Inc.
@@ -38,6 +39,15 @@
# error "This kernel is too old: not supported by this file"
#endif
+/*
+ * NOTE: (only applies to kernel 2.6)
+ * If using an i386 architecture without a PC real-time clock,
+ * the #define USE_RTC should be commented out.
+ */
+#if defined(__i386__)
+#define USE_RTC
+#endif
+
#include <linux/kernel.h>
#include <linux/errno.h>
#include <linux/module.h>
@@ -54,6 +64,9 @@
#include <asm/io.h>
#endif
#ifdef LINUX26
+#ifdef USE_RTC
+#include <linux/rtc.h>
+#endif
#include <linux/moduleparam.h>
#endif
#include "ztdummy.h"
@@ -77,8 +90,10 @@ static struct ztdummy *ztd;
static int debug = 0;
#ifdef LINUX26
+#ifndef USE_RTC
/* New 2.6 kernel timer stuff */
static struct timer_list timer;
+#endif
#else
#if LINUX_VERSION_CODE < VERSION_CODE(2,4,5)
# error "This kernel is too old: not supported by this file"
@@ -103,6 +118,28 @@ extern uhci_t **uhci_devices;
#ifdef LINUX26
+#ifdef USE_RTC
+/* rtc_interrupt - called at 1024Hz from hook in RTC handler */
+static void rtc_interrupt(void *private_data)
+{
+ struct ztdummy *ztd = private_data;
+ unsigned int ticks;
+
+ atomic_inc(&ztd->ticks);
+ ticks = atomic_read(&ztd->ticks);
+ if (ticks == 42 || ticks == 85) {
+ /* skip it */
+ } else if (ticks >= 128) {
+ /* skip and restart count */
+ atomic_set(&ztd->ticks, 0);
+ } else {
+ /* zaptel timing - called in 125 of every 128 interrupts = 1000Hz */
+ zt_receive(&ztd->span);
+ zt_transmit(&ztd->span);
+ }
+}
+#else
+/* use kernel system tick timer if PC architecture RTC is not available */
static void ztdummy_timer(unsigned long param)
{
zt_receive(&ztd->span);
@@ -110,6 +147,7 @@ static void ztdummy_timer(unsigned long param)
timer.expires = jiffies + 1;
add_timer(&timer);
}
+#endif
#else
static void ztdummy_interrupt(int irq, void *dev_id, struct pt_regs *regs)
{
@@ -150,7 +188,11 @@ static int ztdummy_initialize(struct ztdummy *ztd)
int init_module(void)
{
-#ifndef LINUX26
+#ifdef LINUX26
+#ifdef USE_RTC
+ int err;
+#endif
+#else
int irq;
spinlock_t mylock = SPIN_LOCK_UNLOCKED;
@@ -180,10 +222,25 @@ int init_module(void)
}
#ifdef LINUX26
+#ifdef USE_RTC
+ atomic_set(&ztd->ticks, 0);
+ ztd->rtc_task.func = rtc_interrupt;
+ ztd->rtc_task.private_data = ztd;
+ err = rtc_register(&ztd->rtc_task);
+ if (err < 0) {
+ printk("ztdummy: Unable to register zaptel rtc driver\n");
+ zt_unregister(&ztd->span);
+ kfree(ztd);
+ return err;
+ }
+ rtc_control(&ztd->rtc_task, RTC_IRQP_SET, 1024); /* 1024 Hz */
+ rtc_control(&ztd->rtc_task, RTC_PIE_ON, 0);
+#else
init_timer(&timer);
timer.function = ztdummy_timer;
timer.expires = jiffies + 1;
add_timer(&timer);
+#endif
#else
irq=s->irq;
spin_lock_irq(&mylock);
@@ -214,7 +271,12 @@ int init_module(void)
void cleanup_module(void)
{
#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