diff options
author | markster <markster@5390a7c7-147a-4af0-8ec9-7488f05a26cb> | 2003-03-20 06:50:06 +0000 |
---|---|---|
committer | markster <markster@5390a7c7-147a-4af0-8ec9-7488f05a26cb> | 2003-03-20 06:50:06 +0000 |
commit | b722b4412c37e15bfe011166a81f187e8e058ef2 (patch) | |
tree | e00dd382a721dbd52b53ad0dec1121c192977504 | |
parent | 2be2fd790835e01f7051580cc7b178f4ea510689 (diff) |
Add programmable timer support to zaptel
git-svn-id: http://svn.digium.com/svn/zaptel/trunk@158 5390a7c7-147a-4af0-8ec9-7488f05a26cb
-rwxr-xr-x | Makefile | 10 | ||||
-rwxr-xr-x | zaptel.c | 144 | ||||
-rwxr-xr-x | zaptel.h | 10 |
3 files changed, 162 insertions, 2 deletions
@@ -88,7 +88,7 @@ all: $(MODULES) ztcfg torisatool makefw ztmonitor ztspeed $(ZTTOOL) devel: tor2ee -tests: patgen pattest patlooptest hdlcstress hdlctest hdlcgen hdlcverify +tests: patgen pattest patlooptest hdlcstress hdlctest hdlcgen hdlcverify timertest tor2.o: tor2.c tor2-hw.h tor.h tor2fw.h zaptel.h gcc $(KFLAGS) -c tor2.c @@ -205,11 +205,17 @@ devices: rm -f $(INSTALL_PREFIX)/dev/zap/ctl rm -f $(INSTALL_PREFIX)/dev/zap/channel rm -f $(INSTALL_PREFIX)/dev/zap/pseudo + rm -f $(INSTALL_PREFIX)/dev/zap/timer + rm -f $(INSTALL_PREFIX)/dev/zap/253 + rm -f $(INSTALL_PREFIX)/dev/zap/252 + rm -f $(INSTALL_PREFIX)/dev/zap/251 + rm -f $(INSTALL_PREFIX)/dev/zap/250 mknod $(INSTALL_PREFIX)/dev/zap/ctl c 196 0 + mknod $(INSTALL_PREFIX)/dev/zap/timer c 196 253 mknod $(INSTALL_PREFIX)/dev/zap/channel c 196 254 mknod $(INSTALL_PREFIX)/dev/zap/pseudo c 196 255 N=1; \ - while [ $$N -lt 253 ]; do \ + while [ $$N -lt 250 ]; do \ rm -f $(INSTALL_PREFIX)/dev/zap/$$N; \ mknod $(INSTALL_PREFIX)/dev/zap/$$N c 196 $$N; \ N=$$[$$N+1]; \ @@ -263,6 +263,16 @@ static inline void zt_kernel_fpu_begin(void) } #endif +static struct zt_timer { + int ms; /* Countdown */ + int pos; /* Position */ + int tripped; /* Whether we're tripped */ + struct zt_timer *next; /* Linked list */ + wait_queue_head_t sel; +} *zaptimers = NULL; + +static spinlock_t zaptimerlock = SPIN_LOCK_UNLOCKED; + struct zt_zone { char name[40]; /* Informational, only */ int ringcadence[ZT_MAX_CADENCE]; @@ -1840,7 +1850,56 @@ static int initialize_channel(struct zt_chan *chan) return 0; } +static int zt_timing_open(struct inode *inode, struct file *file) +{ + struct zt_timer *t; + long flags; + t = kmalloc(sizeof(struct zt_timer), GFP_KERNEL); + if (!t) + return -ENOMEM; + /* Allocate a new timer */ + memset(t, 0, sizeof(struct zt_timer)); + init_waitqueue_head(&t->sel); + file->private_data = t; + MOD_INC_USE_COUNT; + spin_lock_irqsave(&zaptimerlock, flags); + t->next = zaptimers; + zaptimers = t; + spin_unlock_irqrestore(&zaptimerlock, flags); + return 0; +} +static int zt_timer_release(struct inode *inode, struct file *file) +{ + struct zt_timer *t, *cur, *prev; + long flags; + t = file->private_data; + if (t) { + spin_lock_irqsave(&zaptimerlock, flags); + prev = NULL; + cur = zaptimers; + while(cur) { + if (t == cur) + break; + prev = cur; + cur = cur->next; + } + if (cur) { + if (prev) + prev->next = cur->next; + else + zaptimers = cur->next; + } + spin_unlock_irqrestore(&zaptimerlock, flags); + if (!cur) { + printk("Zap Timer: Not on list??\n"); + return 0; + } + kfree(t); + MOD_DEC_USE_COUNT; + } + return 0; +} static int zt_specchan_open(struct inode *inode, struct file *file, int unit, int inc) { @@ -1922,6 +1981,8 @@ static int zt_open(struct inode *inode, struct file *file) /* Minor 0: Special "control" descriptor */ if (!unit) return zt_ctl_open(inode, file); + if (unit == 253) + return zt_timing_open(inode, file); if (unit == 254) return zt_chan_open(inode, file); if (unit == 255) { @@ -1946,6 +2007,9 @@ static ssize_t zt_read(struct file *file, char *usrbuf, size_t count, loff_t *pp return -EINVAL; } + if (unit == 253) + return -EINVAL; + if (unit == 254) { chan = file->private_data; if (!chan) @@ -1976,6 +2040,8 @@ static ssize_t zt_write(struct file *file, const char *usrbuf, size_t count, lof return -EINVAL; if (count < 0) return -EINVAL; + if (unit == 253) + return -EINVAL; if (unit == 254) { chan = file->private_data; if (!chan) @@ -2188,6 +2254,9 @@ static int zt_release(struct inode *inode, struct file *file) if (!unit) return zt_ctl_release(inode, file); + if (unit == 253) { + return zt_timer_release(inode, file); + } if (unit == 254) { chan = file->private_data; if (!chan) @@ -2254,6 +2323,32 @@ void zt_alarm_notify(struct zt_span *span) return -ENXIO; \ } while(0) +static int zt_timer_ioctl(struct inode *node, struct file *file, unsigned int cmd, unsigned long data, struct zt_timer *timer) +{ + int j; + unsigned long flags; + switch(cmd) { + case ZT_TIMERCONFIG: + get_user(j, (int *)data); + if (j < 0) + j = 0; + spin_lock_irqsave(&zaptimerlock, flags); + timer->ms = timer->pos = j; + spin_unlock_irqrestore(&zaptimerlock, flags); + break; + case ZT_TIMERACK: + get_user(j, (int *)data); + spin_lock_irqsave(&zaptimerlock, flags); + if ((j < 1) || (j > timer->tripped)) + j = timer->tripped; + timer->tripped -= j; + spin_unlock_irqrestore(&zaptimerlock, flags); + break; + default: + return -ENOTTY; + } + return 0; +} static int zt_common_ioctl(struct inode *node, struct file *file, unsigned int cmd, unsigned long data, int unit) { struct zt_gains gain; @@ -3597,9 +3692,17 @@ static int zt_ioctl(struct inode *inode, struct file *file, unsigned int cmd, un { int unit = UNIT(file); struct zt_chan *chan; + struct zt_timer *timer; if (!unit) return zt_ctl_ioctl(inode, file, cmd, data); + if (unit == 253) { + timer = file->private_data; + if (timer) + return zt_timer_ioctl(inode, file, cmd, data, timer); + else + return -EINVAL; + } if (unit == 254) { chan = file->private_data; if (chan) @@ -4977,6 +5080,41 @@ out in the later versions, and is put back now. */ } } +static void process_timers(void) +{ + long flags; + struct zt_timer *cur; + spin_lock_irqsave(&zaptimerlock, flags); + cur = zaptimers; + while(cur) { + if (cur->ms) { + cur->pos -= ZT_CHUNKSIZE; + if (cur->pos <= 0) { + cur->tripped++; + cur->pos = cur->ms; + wake_up_interruptible(&cur->sel); + } + } + cur = cur->next; + } + spin_unlock_irqrestore(&zaptimerlock, flags); +} + +static unsigned int zt_timer_poll(struct file *file, struct poll_table_struct *wait_table) +{ + struct zt_timer *timer = file->private_data; + long flags; + int ret = 0; + if (timer) { + poll_wait(file, &timer->sel, wait_table); + spin_lock_irqsave(&zaptimerlock, flags); + if (timer->tripped) + ret |= POLLPRI; + spin_unlock_irqrestore(&zaptimerlock, flags); + } else + ret = -EINVAL; + return ret; +} /* device poll routine */ static unsigned int @@ -5017,6 +5155,10 @@ static unsigned int zt_poll(struct file *file, struct poll_table_struct *wait_ta if (!unit) return -EINVAL; + + if (unit == 253) + return zt_timer_poll(file, wait_table); + if (unit == 254) { chan = file->private_data; if (!chan) @@ -5262,6 +5404,8 @@ int zt_receive(struct zt_span *span) } if (span == master) { + /* Process any timers */ + process_timers(); /* If we have dynamic stuff, call the ioctl with 0,0 parameters to make it run */ if (zt_dynamic_ioctl) @@ -524,6 +524,16 @@ char dialstr[ZT_MAX_DTMF_BUF]; #define ZT_SFCONFIG _IOW (ZT_CODE, 46, struct zt_sfconfig) /* + * Set timer expiration (in samples) + */ +#define ZT_TIMERCONFIG _IOW (ZT_CODE, 47, int) + +/* + * Acknowledge timer expiration (number to acknowledge, or -1 for all) + */ +#define ZT_TIMERACK _IOW (ZT_CODE, 48, int) + +/* * 60-80 are reserved for private drivers * 80-85 are reserved for dynamic span stuff */ |