From b1d3b9a5b437b65247a670352ce2abbf28decff8 Mon Sep 17 00:00:00 2001 From: markster Date: Sun, 5 Oct 2003 19:27:13 +0000 Subject: First pass at eliminating excessive OHT usage git-svn-id: http://svn.digium.com/svn/zaptel/trunk@251 5390a7c7-147a-4af0-8ec9-7488f05a26cb --- wctdm.c | 118 ++++++++++++++++++++++++++++++++++++++-------------------------- 1 file changed, 70 insertions(+), 48 deletions(-) (limited to 'wctdm.c') diff --git a/wctdm.c b/wctdm.c index 22702a0..b778d37 100755 --- a/wctdm.c +++ b/wctdm.c @@ -132,6 +132,8 @@ static alpha indirect_regs[] = #define RING_DEBOUNCE 64 /* Ringer Debounce (in ms) */ #define BATT_DEBOUNCE 8 /* Battery debounce (in ms) */ +#define OHT_TIMER 6000 /* How long after RING to retain OHT */ + #define FLAG_DOUBLE_CLOCK (1 << 0) #define NUM_CARDS 4 @@ -160,6 +162,7 @@ struct wcfxs { int debouncehook[NUM_CARDS]; int lastrxhook[NUM_CARDS]; int debounce[NUM_CARDS]; + int ohttimer[NUM_CARDS]; int idletxhookstate[NUM_CARDS]; /* IDLE changing hook state */ int lasttxhook[NUM_CARDS]; @@ -252,51 +255,6 @@ static void wcfxs_stop_dma(struct wcfxs *wc); static void wcfxs_reset_tdm(struct wcfxs *wc); static void wcfxs_restart_dma(struct wcfxs *wc); -static void wcfxs_interrupt(int irq, void *dev_id, struct pt_regs *regs) -{ - struct wcfxs *wc = dev_id; - unsigned char ints; - int x; - - ints = inb(wc->ioaddr + WC_INTSTAT); - outb(ints, wc->ioaddr + WC_INTSTAT); - - if (!ints) - return; - - if (ints & 0x10) { - /* Stop DMA, wait for watchdog */ - printk("FXS PCI Master abort\n"); - wcfxs_stop_dma(wc); - return; - } - - if (ints & 0x20) { - printk("PCI Target abort\n"); - return; - } - - - if (ints & 0x0f) { - wc->intcount++; - x = wc->intcount % 4; - if ((x < wc->cards) && (wc->cardflag & (1 << x))) { - wcfxs_check_hook(wc, x); - if (!(wc->intcount & 0xfc)) - wcfxs_recheck_sanity(wc, x); - } - if (!(wc->intcount % 10000)) { - /* Accept an alarm once per 10 seconds */ - for (x=0;x<4;x++) - if (wc->palarms[x]) - wc->palarms[x]--; - } - wcfxs_receiveprep(wc, ints); - wcfxs_transmitprep(wc, ints); - } - -} - static inline void write_8bits(struct wcfxs *wc, unsigned char bits) { /* Drop chip select */ @@ -513,6 +471,73 @@ static int wcfxs_verify_indirect_regs(struct wcfxs *wc, int card) return 0; } +static void wcfxs_interrupt(int irq, void *dev_id, struct pt_regs *regs) +{ + struct wcfxs *wc = dev_id; + unsigned char ints; + int x; + + ints = inb(wc->ioaddr + WC_INTSTAT); + outb(ints, wc->ioaddr + WC_INTSTAT); + + if (!ints) + return; + + if (ints & 0x10) { + /* Stop DMA, wait for watchdog */ + printk("FXS PCI Master abort\n"); + wcfxs_stop_dma(wc); + return; + } + + if (ints & 0x20) { + printk("PCI Target abort\n"); + return; + } + + for (x=0;x<4;x++) { + if ((x < wc->cards) && (wc->cardflag & (1 << x))) { + if (wc->lasttxhook[x] == 0x4) { + /* RINGing, prepare for OHT */ + wc->ohttimer[x] = OHT_TIMER; + wc->idletxhookstate[x] = 0x2; /* OHT mode when idle */ + } else { + if (wc->ohttimer[x]) { + wc->ohttimer[x]-= ZT_CHUNKSIZE; + if (!wc->ohttimer[x]) { + wc->idletxhookstate[x] = 0x1; /* Switch to active */ + if (wc->lasttxhook[x] == 0x2) { + /* Apply the change if appropriate */ + wc->lasttxhook[x] = 0x1; + wcfxs_setreg(wc, x, 64, wc->lasttxhook[x]); + } + } + } + } + } + } + + if (ints & 0x0f) { + wc->intcount++; + x = wc->intcount % 4; + if ((x < wc->cards) && (wc->cardflag & (1 << x))) { + wcfxs_check_hook(wc, x); + if (!(wc->intcount & 0xfc)) + wcfxs_recheck_sanity(wc, x); + } + if (!(wc->intcount % 10000)) { + /* Accept an alarm once per 10 seconds */ + for (x=0;x<4;x++) + if (wc->palarms[x]) + wc->palarms[x]--; + } + wcfxs_receiveprep(wc, ints); + wcfxs_transmitprep(wc, ints); + } + + +} + static int wcfxs_proslic_insane(struct wcfxs *wc, int card) { int blah,insane_report; @@ -1025,14 +1050,11 @@ static int wcfxs_ioctl(struct zt_chan *chan, unsigned int cmd, unsigned long dat static int wcfxs_open(struct zt_chan *chan) { struct wcfxs *wc = chan->pvt; - int x; if (!(wc->cardflag & (1 << (chan->chanpos - 1)))) return -ENODEV; if (wc->dead) return -ENODEV; wc->usecount++; - for (x=0;xcards;x++) - wc->idletxhookstate[x] = 2; MOD_INC_USE_COUNT; return 0; } -- cgit v1.2.3