summaryrefslogtreecommitdiff
path: root/wct1xxp.c
diff options
context:
space:
mode:
authormarkster <markster@5390a7c7-147a-4af0-8ec9-7488f05a26cb>2002-02-11 17:23:02 +0000
committermarkster <markster@5390a7c7-147a-4af0-8ec9-7488f05a26cb>2002-02-11 17:23:02 +0000
commit58fb517415c5971aa4feb3bb84bfa9bad26bea63 (patch)
tree6ef2d00fdfd08d9f605f3972ba28a70a2e4fd26f /wct1xxp.c
parent380f566d2174975558b56ad0723da74857571b0c (diff)
Version 0.1.6 from FTP
git-svn-id: http://svn.digium.com/svn/zaptel/trunk@55 5390a7c7-147a-4af0-8ec9-7488f05a26cb
Diffstat (limited to 'wct1xxp.c')
-rwxr-xr-xwct1xxp.c464
1 files changed, 313 insertions, 151 deletions
diff --git a/wct1xxp.c b/wct1xxp.c
index 82a634c..c612f59 100755
--- a/wct1xxp.c
+++ b/wct1xxp.c
@@ -41,7 +41,9 @@
#define WC_MAX_CARDS 32
+/*
#define TEST_REGS
+*/
/* Define to get more attention-grabbing but slightly more I/O using
alarm status */
@@ -79,11 +81,23 @@
#define WC_OFFSET 4
#define BIT_CS (1 << 7)
-
-#define BIT_OK (1 << 0)
-#define BIT_TEST (1 << 1)
-#define BIT_ERROR (1 << 2)
-#define BIT_ALARM (1 << 3)
+#define BIT_ADDR (0xf << 3)
+
+#define BIT_LED0 (1 << 0)
+#define BIT_LED1 (1 << 1)
+#define BIT_TEST (1 << 2)
+
+static char *chips[] =
+{
+ "DS2152",
+ "DS21352",
+ "DS21552",
+ "Unknown Chip (3)",
+ "DS2154",
+ "DS21354",
+ "DS21554",
+ "Unknown Chip (4)",
+};
static int chanmap[] =
{ 2,1,0,
@@ -108,11 +122,11 @@ struct t1xxp {
/* Our offset for finding channel 1 */
int offset;
char *variety;
+ int intcount;
int usecount;
int dead;
+ int blinktimer;
int alarmtimer;
- int alarm;
- int alreadyrunning;
#ifdef FANCY_ALARM
int alarmpos;
#endif
@@ -133,31 +147,30 @@ static struct t1xxp *cards[WC_MAX_CARDS];
static inline void start_alarm(struct t1xxp *wc)
{
- wc->alarm = 1;
#ifdef FANCY_ALARM
wc->alarmpos = 0;
#endif
- wc->alarmtimer = 0;
+ wc->blinktimer = 0;
}
static inline void stop_alarm(struct t1xxp *wc)
{
- wc->alarm = 0;
#ifdef FANCY_ALARM
wc->alarmpos = 0;
#endif
- wc->alarmtimer = 0;
+ wc->blinktimer = 0;
}
-static inline void select_framer(struct t1xxp *wc)
+static inline void __select_framer(struct t1xxp *wc, int reg)
{
- if (wc->outbyte & BIT_CS) {
- wc->outbyte &= ~BIT_CS;
- outb(wc->outbyte, wc->ioaddr + WC_AUXD);
- }
+ /* Top four bits of address from AUX 6-3 */
+ wc->outbyte &= ~BIT_CS;
+ wc->outbyte &= ~BIT_ADDR;
+ wc->outbyte |= (reg & 0xf0) >> 1;
+ outb(wc->outbyte, wc->ioaddr + WC_AUXD);
}
-static inline void select_control(struct t1xxp *wc)
+static inline void __select_control(struct t1xxp *wc)
{
if (!(wc->outbyte & BIT_CS)) {
wc->outbyte |= BIT_CS;
@@ -175,41 +188,58 @@ static int t1xxp_open(struct zt_chan *chan)
return 0;
}
-static int t1_get_reg(struct t1xxp *wc, int reg)
+static int __t1_get_reg(struct t1xxp *wc, int reg)
{
unsigned char res;
- select_framer(wc);
- /* Send address */
- outb(reg & 0xff, wc->ioaddr + WC_USERREG + 4);
+ __select_framer(wc, reg);
/* Get value */
- res = inb(wc->ioaddr + WC_USERREG);
+ res = inb(wc->ioaddr + WC_USERREG + ((reg & 0xf) << 2));
return res;
}
-static int t1_set_reg(struct t1xxp *wc, int reg, unsigned char val)
+static int __t1_set_reg(struct t1xxp *wc, int reg, unsigned char val)
{
- select_framer(wc);
+ __select_framer(wc, reg);
/* Send address */
- outb(reg & 0xff, wc->ioaddr + WC_USERREG + 4);
- outb(val, wc->ioaddr + WC_USERREG);
+ outb(val, wc->ioaddr + WC_USERREG + ((reg & 0xf) << 2));
return 0;
}
-static int control_set_reg(struct t1xxp *wc, int reg, unsigned char val)
+static int __control_set_reg(struct t1xxp *wc, int reg, unsigned char val)
{
- select_control(wc);
+ __select_control(wc);
outb(val, wc->ioaddr + WC_USERREG + ((reg & 0xf) << 2));
return 0;
}
-static int control_get_reg(struct t1xxp *wc, int reg)
+static int control_set_reg(struct t1xxp *wc, int reg, unsigned char val)
+{
+ long flags;
+ int res;
+ spin_lock_irqsave(&wc->lock, flags);
+ res = __control_set_reg(wc, reg, val);
+ spin_unlock_irqrestore(&wc->lock, flags);
+ return res;
+}
+
+static int __control_get_reg(struct t1xxp *wc, int reg)
{
unsigned char res;
- select_control(wc);
+ __select_control(wc);
res = inb(wc->ioaddr + WC_USERREG + ((reg & 0xf) << 2));
return res;
}
+static int control_get_reg(struct t1xxp *wc, int reg)
+{
+ long flags;
+ int res;
+ spin_lock_irqsave(&wc->lock, flags);
+ res = __control_get_reg(wc, reg);
+ spin_unlock_irqrestore(&wc->lock, flags);
+ return res;
+}
+
static void t1xxp_release(struct t1xxp *wc)
{
zt_unregister(&wc->span);
@@ -249,12 +279,12 @@ static void t1xxp_start_dma(struct t1xxp *wc)
printk("Started DMA\n");
}
-static void t1xxp_stop_dma(struct t1xxp *wc)
+static void __t1xxp_stop_dma(struct t1xxp *wc)
{
outb(0x00, wc->ioaddr + WC_OPER);
}
-static void t1xxp_disable_interrupts(struct t1xxp *wc)
+static void __t1xxp_disable_interrupts(struct t1xxp *wc)
{
outb(0x00, wc->ioaddr + WC_MASK0);
outb(0x00, wc->ioaddr + WC_MASK1);
@@ -265,6 +295,11 @@ static void t1xxp_framer_start(struct t1xxp *wc)
int i;
char *coding, *framing;
unsigned long endjiffies;
+ int alreadyrunning = wc->span.flags & ZT_FLAG_RUNNING;
+ long flags;
+
+ spin_lock_irqsave(&wc->lock, flags);
+
/* Build up config */
i = 0x20;
if (wc->span.lineconfig & ZT_CONFIG_ESF) {
@@ -279,105 +314,101 @@ static void t1xxp_framer_start(struct t1xxp *wc)
} else {
framing = "AMI";
}
- t1_set_reg(wc, 0x38, i);
+ __t1_set_reg(wc, 0x38, i);
if (!(wc->span.lineconfig & ZT_CONFIG_ESF)) {
/* 1c in FDL bit */
- t1_set_reg(wc, 0x7e, 0x1c);
+ __t1_set_reg(wc, 0x7e, 0x1c);
} else {
- t1_set_reg(wc, 0x7e, 0x00);
+ __t1_set_reg(wc, 0x7e, 0x00);
}
/* Set outgoing LBO */
- t1_set_reg(wc, 0x7c, wc->span.txlevel << 5);
+ __t1_set_reg(wc, 0x7c, wc->span.txlevel << 5);
printk("Using %s/%s coding/framing\n", coding, framing);
- if (!wc->alreadyrunning) {
+ if (!alreadyrunning) {
/* Set LIRST bit to 1 */
- t1_set_reg(wc, 0x30, 0x1);
+ __t1_set_reg(wc, 0x0a, 0x80);
+ spin_unlock_irqrestore(&wc->lock, flags);
/* Wait 100ms to give plenty of time for reset */
endjiffies = jiffies + 10;
while(endjiffies < jiffies);
- /* Reset elastic stores */
- t1_set_reg(wc, 0x30, 0x40);
- wc->alreadyrunning = 1;
- }
-#if 0
- {
- t1_set_reg(wc, 0x3c, 0xff);
- t1_set_reg(wc, 0x3d, 0xff);
- t1_set_reg(wc, 0x3e, 0xff);
- int x;
- for (i=0x20;i<0x40;i++) {
- x = t1_get_reg(wc, i);
- if (x)
- printk("%02x: %02x\n", i, x);
- }
- for (i=0x60;i<0x80;i++) {
- x = t1_get_reg(wc, i);
- if (x)
- printk("%02x: %02x\n", i, x);
- }
+ spin_lock_irqsave(&wc->lock, flags);
+
+ /* Reset LIRST bit and reset elastic stores */
+ __t1_set_reg(wc, 0xa, 0x30);
+
+ wc->span.flags |= ZT_FLAG_RUNNING;
}
-#endif
+ spin_unlock_irqrestore(&wc->lock, flags);
+}
+
+static int t1xxp_framer_sanity_check(struct t1xxp *wc)
+{
+ int res;
+ int chipid;
+ long flags;
+
+ /* Sanity check */
+ spin_lock_irqsave(&wc->lock, flags);
+ res = __t1_get_reg(wc, 0x0f);
+ chipid = ((res & 0x80) >> 5) | ((res & 0x30) >> 4);
+ spin_unlock_irqrestore(&wc->lock, flags);
+
+ printk("Framer: %s, Revision: %d\n", chips[chipid], res & 0xf);
+ return 0;
}
static int t1xxp_framer_hard_reset(struct t1xxp *wc)
{
int x;
+ long flags;
+
+ spin_lock_irqsave(&wc->lock, flags);
/* Initialize all registers to 0 */
- for (x=0x20;x<0x40;x++)
- t1_set_reg(wc, x, 0);
- for (x=0x60;x<0x80;x++)
- t1_set_reg(wc, x, 0);
+ for (x=0x0;x<0x96;x++)
+ __t1_set_reg(wc, x, 0);
/* Full-on sync required */
- t1_set_reg(wc, 0x2b, 0x08);
+ __t1_set_reg(wc, 0x2b, 0x08);
/* RSYNC is an input */
- t1_set_reg(wc, 0x2c, 0x08);
+ __t1_set_reg(wc, 0x2c, 0x08);
/* Enable tx RBS bits */
- t1_set_reg(wc, 0x35, 0x10);
+ __t1_set_reg(wc, 0x35, 0x10);
/* TSYNC is output */
- t1_set_reg(wc, 0x36, 0x04);
+ __t1_set_reg(wc, 0x36, 0x04);
/* Tx and Rx elastic store enabled, 2.048 Mhz (in theory) */
- t1_set_reg(wc, 0x37, 0x8c);
-#ifdef TEST_REGS
- printk("Testing framer registers...\n");
- t1_set_reg(wc, 0x6c, 0xff);
- printk("Expecting ff, got %02x\n", t1_get_reg(wc, 0x6c));
- t1_set_reg(wc, 0x6c, 0x00);
- printk("Expecting 00, got %02x\n", t1_get_reg(wc, 0x6c));
- t1_set_reg(wc, 0x6c, 0xaa);
- printk("Expecting aa, got %02x\n", t1_get_reg(wc, 0x6c));
- t1_set_reg(wc, 0x6c, 0x55);
- printk("Expecting 55, got %02x\n", t1_get_reg(wc, 0x6c));
- t1_set_reg(wc, 0x6c, 0x00);
- printk("Testing control registers...\n");
- control_set_reg(wc, WC_LEDTEST, 0xff);
- printk("Expecting ff, got %02x\n", control_get_reg(wc, WC_LEDTEST));
- control_set_reg(wc, WC_LEDTEST, 0x00);
- printk("Expecting 00, got %02x\n", control_get_reg(wc, WC_LEDTEST));
- control_set_reg(wc, WC_LEDTEST, 0xaa);
- printk("Expecting aa, got %02x\n", control_get_reg(wc, WC_LEDTEST));
- control_set_reg(wc, WC_LEDTEST, 0x55);
- printk("Expecting 55, got %02x\n", control_get_reg(wc, WC_LEDTEST));
- control_set_reg(wc, WC_LEDTEST, 0x00);
-#endif
+ __t1_set_reg(wc, 0x37, 0x9c);
+
+ /* Setup Loopup / Loopdown codes */
+ __t1_set_reg(wc, 0x12, 0x22);
+ __t1_set_reg(wc, 0x14, 0x80);
+ __t1_set_reg(wc, 0x15, 0x80);
+ spin_unlock_irqrestore(&wc->lock, flags);
return 0;
}
static int t1xxp_rbsbits(struct zt_chan *chan, int bits)
{
struct t1xxp *wc = chan->pvt;
+ long flags;
+ int b,o;
+ unsigned char mask;
+
/* Byte offset */
- int b = (chan->chanpos - 1) / 8;
- int o = (chan->chanpos - 1) % 8;
- unsigned char mask = (1 << o);
+ spin_lock_irqsave(&wc->lock, flags);
+
+ b = (chan->chanpos - 1) / 8;
+ o = (chan->chanpos - 1) % 8;
+
+ mask = (1 << o);
+
if (bits & ZT_ABIT) {
/* Set A-bit */
wc->txsiga[b] |= mask;
@@ -392,10 +423,11 @@ static int t1xxp_rbsbits(struct zt_chan *chan, int bits)
wc->txsigb[b] &= ~mask;
}
/* Output new values */
- t1_set_reg(wc, 0x70 + b, wc->txsiga[b]);
- t1_set_reg(wc, 0x73 + b, wc->txsigb[b]);
- t1_set_reg(wc, 0x76 + b, wc->txsiga[b]);
- t1_set_reg(wc, 0x79 + b, wc->txsigb[b]);
+ __t1_set_reg(wc, 0x70 + b, wc->txsiga[b]);
+ __t1_set_reg(wc, 0x73 + b, wc->txsigb[b]);
+ __t1_set_reg(wc, 0x76 + b, wc->txsiga[b]);
+ __t1_set_reg(wc, 0x79 + b, wc->txsigb[b]);
+ spin_unlock_irqrestore(&wc->lock, flags);
return 0;
}
@@ -412,6 +444,7 @@ static int t1xxp_startup(struct zt_span *span)
struct t1xxp *wc = span->pvt;
/* Reset framer with proper parameters and start */
t1xxp_framer_start(wc);
+
if (!(span->flags & ZT_FLAG_RUNNING)) {
/* Only if we're not already going */
t1xxp_enable_interrupts(wc);
@@ -424,9 +457,15 @@ static int t1xxp_startup(struct zt_span *span)
static int t1xxp_shutdown(struct zt_span *span)
{
struct t1xxp *wc = span->pvt;
- t1xxp_stop_dma(wc);
- t1xxp_disable_interrupts(wc);
+ long flags;
+
+ spin_lock_irqsave(&wc->lock, flags);
+ __t1xxp_stop_dma(wc);
+ __t1xxp_disable_interrupts(wc);
span->flags &= ~ZT_FLAG_RUNNING;
+ spin_unlock_irqrestore(&wc->lock, flags);
+
+ t1xxp_framer_hard_reset(wc);
return 0;
}
@@ -436,7 +475,7 @@ static int t1xxp_maint(struct zt_span *span, int mode)
return -1;
}
-static void t1xxp_set_clear(struct t1xxp *wc)
+static void __t1xxp_set_clear(struct t1xxp *wc)
{
/* Setup registers */
int x,y;
@@ -446,7 +485,7 @@ static void t1xxp_set_clear(struct t1xxp *wc)
for (y=0;y<8;y++)
if (wc->chans[x * 8 + y].sig & ZT_SIG_CLEAR)
b |= (1 << y);
- t1_set_reg(wc, 0x39 + x, b);
+ __t1_set_reg(wc, 0x39 + x, b);
}
}
@@ -455,9 +494,12 @@ static int t1xxp_chanconfig(struct zt_chan *chan, int sigtype)
struct t1xxp *wc = chan->pvt;
int flags;
int alreadyrunning = chan->span->flags & ZT_FLAG_RUNNING;
+
spin_lock_irqsave(&wc->lock, flags);
+
if (alreadyrunning)
- t1xxp_set_clear(wc);
+ __t1xxp_set_clear(wc);
+
spin_unlock_irqrestore(&wc->lock, flags);
return 0;
}
@@ -504,6 +546,7 @@ static int t1xxp_software_init(struct t1xxp *wc)
wc->span.linecompat = ZT_CONFIG_AMI | ZT_CONFIG_B8ZS | ZT_CONFIG_D4 | ZT_CONFIG_ESF;
wc->span.ioctl = t1xxp_ioctl;
wc->span.pvt = wc;
+ wc->span.deflaw = ZT_LAW_MULAW;
init_waitqueue_head(&wc->span.maintq);
for (x=0;x<24;x++) {
sprintf(wc->chans[x].name, "WCT1/%d/%d", wc->num, x + 1);
@@ -521,34 +564,51 @@ static int t1xxp_software_init(struct t1xxp *wc)
return 0;
}
-static inline void handle_leds(struct t1xxp *wc)
+static inline void __handle_leds(struct t1xxp *wc)
{
- if (wc->alarm) {
+ int oldreg;
+ wc->blinktimer++;
+ if (wc->span.alarms & (ZT_ALARM_RED | ZT_ALARM_BLUE)) {
+ /* Red/Blue alarm */
#ifdef FANCY_ALARM
- if (wc->alarmtimer == (altab[wc->alarmpos] >> 1)) {
- wc->ledtestreg = wc->ledtestreg | BIT_ALARM;
- control_set_reg(wc, WC_LEDTEST, wc->ledtestreg);
+ if (wc->blinktimer == (altab[wc->alarmpos] >> 1)) {
+ wc->ledtestreg = (wc->ledtestreg | BIT_LED1) & ~BIT_LED0;
+ __control_set_reg(wc, WC_LEDTEST, wc->ledtestreg);
}
- if (wc->alarmtimer == 0xf) {
- wc->ledtestreg = wc->ledtestreg & ~BIT_ALARM;
- control_set_reg(wc, WC_LEDTEST, wc->ledtestreg);
- wc->alarmtimer = -1;
+ if (wc->blinktimer == 0xf) {
+ wc->ledtestreg = wc->ledtestreg & ~(BIT_LED0 | BIT_LED1);
+ __control_set_reg(wc, WC_LEDTEST, wc->ledtestreg);
+ wc->blinktimer = -1;
wc->alarmpos++;
if (wc->alarmpos >= (sizeof(altab) / sizeof(altab[0])))
wc->alarmpos = 0;
}
- wc->alarmtimer++;
#else
- wc->alarmtimer++;
- if (wc->alarmtimer == 160) {
- wc->ledtestreg = wc->ledtestreg | BIT_ALARM;
- control_set_reg(wc, WC_LEDTEST, wc->ledtestreg);
- } else if (wc->alarmtimer == 480) {
- wc->ledtestreg = wc->ledtestreg & ~BIT_ALARM;
- control_set_reg(wc, WC_LEDTEST, wc->ledtestreg);
- wc->alarmtimer = 0;
+ if (wc->blinktimer == 160) {
+ wc->ledtestreg = (wc->ledtestreg | BIT_LED1) & ~BIT_LED0;
+ __control_set_reg(wc, WC_LEDTEST, wc->ledtestreg);
+ } else if (wc->blinktimer == 480) {
+ wc->ledtestreg = wc->ledtestreg & ~(BIT_LED0 | BIT_LED1);
+ __control_set_reg(wc, WC_LEDTEST, wc->ledtestreg);
+ wc->blinktimer = 0;
}
#endif
+ } else if (wc->span.alarms & ZT_ALARM_YELLOW) {
+ /* Yellow Alarm */
+ if (!(wc->blinktimer % 2))
+ wc->ledtestreg = (wc->ledtestreg | BIT_LED1) & ~BIT_LED0;
+ else
+ wc->ledtestreg = (wc->ledtestreg | BIT_LED0) & ~BIT_LED1;
+ __control_set_reg(wc, WC_LEDTEST, wc->ledtestreg);
+ } else {
+ /* No Alarm */
+ oldreg = wc->ledtestreg;
+ if (wc->span.flags & ZT_FLAG_RUNNING)
+ wc->ledtestreg = (wc->ledtestreg | BIT_LED0) & ~BIT_LED1;
+ else
+ wc->ledtestreg = wc->ledtestreg & ~(BIT_LED0 | BIT_LED1);
+ if (oldreg != wc->ledtestreg)
+ __control_set_reg(wc, WC_LEDTEST, wc->ledtestreg);
}
}
@@ -606,50 +666,140 @@ static void t1xxp_receiveprep(struct t1xxp *wc, int ints)
zt_receive(&wc->span);
}
+static void __t1xxp_check_sigbits(struct t1xxp *wc, int x)
+{
+ int a,b,i,y,rxs;
+
+ a = __t1_get_reg(wc, 0x60 + x);
+ b = __t1_get_reg(wc, 0x64 + x);
+ for (y=0;y<8;y++) {
+ i = x * 8 + y;
+ rxs = 0;
+ if (a & (1 << y))
+ rxs |= ZT_ABIT;
+ if (b & (1 << y))
+ rxs |= ZT_BBIT;
+ if (!(wc->chans[i].sig & ZT_SIG_CLEAR)) {
+ if (wc->chans[i].rxsig != rxs)
+ zt_rbsbits(&wc->chans[i], rxs);
+ }
+ }
+}
+
+static void __t1xxp_check_alarms(struct t1xxp *wc)
+{
+ unsigned char c;
+ int alarms;
+ int x,j;
+
+ /* Get RIR3 */
+ c = __t1_get_reg(wc, 0x10);
+ wc->span.rxlevel = c >> 6;
+
+ /* Get status register s*/
+ __t1_set_reg(wc, 0x20, 0xff);
+ c = __t1_get_reg(wc, 0x20);
+
+ /* Assume no alarms */
+ alarms = 0;
+
+ /* And consider only carrier alarms */
+ wc->span.alarms &= (ZT_ALARM_RED | ZT_ALARM_BLUE | ZT_ALARM_NOTOPEN);
+
+ if (wc->span.lineconfig & ZT_CONFIG_NOTOPEN) {
+ for (x=0,j=0;x < wc->span.channels;x++)
+ if ((wc->chans[x].flags & ZT_FLAG_OPEN) ||
+ (wc->chans[x].flags & ZT_FLAG_NETDEV))
+ j++;
+ if (!j)
+ alarms |= ZT_ALARM_NOTOPEN;
+ }
+
+ /* Check actual alarm status */
+ if (c & 0x3)
+ alarms |= ZT_ALARM_RED;
+ if (c & 0x8)
+ alarms |= ZT_ALARM_BLUE;
+
+ /* Keep track of recovering */
+ if (!alarms && wc->span.alarms)
+ wc->alarmtimer = ZT_ALARMSETTLE_TIME;
+ if (wc->alarmtimer)
+ alarms |= ZT_ALARM_RECOVER;
+
+ /* If receiving alarms, go into Yellow alarm state */
+ if (alarms && !wc->span.alarms) {
+ printk("Going into yellow alarm\n");
+ __t1_set_reg(wc, 0x35, 0x11);
+ }
+
+ if (c & 0x4)
+ alarms |= ZT_ALARM_YELLOW;
+
+ wc->span.alarms = alarms;
+ zt_alarm_notify(&wc->span);
+
+}
+
+static void __t1xxp_do_counters(struct t1xxp *wc)
+{
+ if (wc->alarmtimer) {
+ if (!--wc->alarmtimer) {
+ wc->span.alarms &= ~ZT_ALARM_RECOVER;
+ /* Clear yellow alarm */
+ printk("Coming out of yellow alarm\n");
+ __t1_set_reg(wc, 0x35, 0x10);
+ zt_alarm_notify(&wc->span);
+ }
+ }
+}
+
static void t1xxp_interrupt(int irq, void *dev_id, struct pt_regs *regs)
{
struct t1xxp *wc = dev_id;
- unsigned char ints, a,b, rxs;
- static int gotint = 0;
- int x,y,i;
+ unsigned char ints;
+ long flags;
+ int x;
ints = inb(wc->ioaddr + WC_INTSTAT);
+ outb(ints, wc->ioaddr + WC_INTSTAT);
+
if (!ints)
return;
- outb(ints, wc->ioaddr + WC_INTSTAT);
- if (!gotint) {
+ if (!wc->intcount) {
printk("Got interrupt: 0x%04x\n", ints);
}
- gotint++;
+ wc->intcount++;
if (ints & 0x0f) {
- t1xxp_transmitprep(wc, ints);
t1xxp_receiveprep(wc, ints);
+ t1xxp_transmitprep(wc, ints);
}
- handle_leds(wc);
+ spin_lock_irqsave(&wc->lock, flags);
-#if 1
- if (!(gotint & 0xf0)) {
- x = gotint & 0xf;
- if (x < 3) {
- a = t1_get_reg(wc, 0x60 + x);
- b = t1_get_reg(wc, 0x64 + x);
- for (y=0;y<8;y++) {
- i = x * 8 + y;
- rxs = 0;
- if (a & (1 << y))
- rxs |= ZT_ABIT;
- if (b & (1 << y))
- rxs |= ZT_BBIT;
- if (!(wc->chans[i].sig & ZT_SIG_CLEAR)) {
- if (wc->chans[i].rxsig != rxs)
- zt_rbsbits(&wc->chans[i], rxs);
- }
- }
- }
- }
+ __handle_leds(wc);
+
+ /* Count down timers */
+ __t1xxp_do_counters(wc);
+
+ /* Do some things that we don't have to do very often */
+ x = wc->intcount & 63;
+ switch(x) {
+ case 0:
+ case 1:
+ case 2:
+ case 3:
+#if 0
+ __t1xxp_check_sigbits(wc, x);
#endif
+ break;
+ case 4:
+ __t1xxp_check_alarms(wc);
+ break;
+ }
+ spin_unlock_irqrestore(&wc->lock, flags);
+
if (ints & 0x10)
printk("PCI Master abort\n");
@@ -698,12 +848,16 @@ static int t1xxp_hardware_init(struct t1xxp *wc)
/* Check out the controller */
printk("Controller version: %02x\n", control_get_reg(wc, WC_VERSION));
+
+
control_set_reg(wc, WC_LEDTEST, 0x00);
control_set_reg(wc, WC_CLOCK, 0x00);
+ if (t1xxp_framer_sanity_check(wc))
+ return -1;
+
/* Reset the T1 and report */
t1xxp_framer_hard_reset(wc);
- /* Pretend we're in alarm */
start_alarm(wc);
return 0;
@@ -720,6 +874,7 @@ static int __devinit t1xxp_init_one(struct pci_dev *pdev, const struct pci_devic
wc = kmalloc(sizeof(struct t1xxp), GFP_KERNEL);
if (wc) {
memset(wc, 0x0, sizeof(struct t1xxp));
+ spin_lock_init(&wc->lock);
wc->ioaddr = pci_resource_start(pdev, 0);
wc->dev = pdev;
wc->variety = (char *)(ent->driver_data);
@@ -773,6 +928,10 @@ static void t1xxp_stop_stuff(struct t1xxp *wc)
/* Turn off LED's */
control_set_reg(wc, WC_LEDTEST, 0);
+
+ /* Reset the T1 */
+ t1xxp_framer_hard_reset(wc);
+
}
static void __devexit t1xxp_remove_one(struct pci_dev *pdev)
@@ -781,10 +940,10 @@ static void __devexit t1xxp_remove_one(struct pci_dev *pdev)
if (wc) {
/* Stop any DMA */
- t1xxp_stop_dma(wc);
+ __t1xxp_stop_dma(wc);
/* In case hardware is still there */
- t1xxp_disable_interrupts(wc);
+ __t1xxp_disable_interrupts(wc);
t1xxp_stop_stuff(wc);
@@ -833,6 +992,9 @@ static void __exit t1xxp_cleanup(void)
MODULE_PARM(debug, "i");
MODULE_DESCRIPTION("Wildcard T100P Zaptel Driver");
MODULE_AUTHOR("Mark Spencer <markster@linux-support.net>");
+#ifdef MODULE_LICENSE
+MODULE_LICENSE("GPL");
+#endif
module_init(t1xxp_init);
module_exit(t1xxp_cleanup);