summaryrefslogtreecommitdiff
path: root/wctdm.c
diff options
context:
space:
mode:
authormarkster <markster@5390a7c7-147a-4af0-8ec9-7488f05a26cb>2003-10-05 19:27:13 +0000
committermarkster <markster@5390a7c7-147a-4af0-8ec9-7488f05a26cb>2003-10-05 19:27:13 +0000
commitb1d3b9a5b437b65247a670352ce2abbf28decff8 (patch)
treeea3e061d2685ffab8bbadf43e58bce4bb54cd88f /wctdm.c
parentf062dbb1c9cc4991938a144bc5d1125fad1904dc (diff)
First pass at eliminating excessive OHT usage
git-svn-id: http://svn.digium.com/svn/zaptel/trunk@251 5390a7c7-147a-4af0-8ec9-7488f05a26cb
Diffstat (limited to 'wctdm.c')
-rwxr-xr-xwctdm.c118
1 files changed, 70 insertions, 48 deletions
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;x<wc->cards;x++)
- wc->idletxhookstate[x] = 2;
MOD_INC_USE_COUNT;
return 0;
}