summaryrefslogtreecommitdiff
path: root/wct1xxp.c
diff options
context:
space:
mode:
authormarkster <markster@5390a7c7-147a-4af0-8ec9-7488f05a26cb>2002-06-19 18:53:18 +0000
committermarkster <markster@5390a7c7-147a-4af0-8ec9-7488f05a26cb>2002-06-19 18:53:18 +0000
commit85d82e003f9dd3cfbc8733a537746750dbd0e5e0 (patch)
tree8a8aa2ffbf957fd4a2b6a170c4bab456b0c586d6 /wct1xxp.c
parentc63dd8597671fa41afb9fe9a1909ace27c6c447c (diff)
Version 0.2.0 from FTP
git-svn-id: http://svn.digium.com/svn/zaptel/trunk@85 5390a7c7-147a-4af0-8ec9-7488f05a26cb
Diffstat (limited to 'wct1xxp.c')
-rwxr-xr-xwct1xxp.c111
1 files changed, 75 insertions, 36 deletions
diff --git a/wct1xxp.c b/wct1xxp.c
index c612f59..45c72d9 100755
--- a/wct1xxp.c
+++ b/wct1xxp.c
@@ -124,6 +124,7 @@ struct t1xxp {
char *variety;
int intcount;
int usecount;
+ int sync;
int dead;
int blinktimer;
int alarmtimer;
@@ -225,7 +226,13 @@ static int control_set_reg(struct t1xxp *wc, int reg, unsigned char val)
static int __control_get_reg(struct t1xxp *wc, int reg)
{
unsigned char res;
- __select_control(wc);
+ /* The following makes UTTERLY no sense, but what was happening
+ was that reads in some cases were not actually happening
+ on the physical bus. Why, we dunno. But in debugging, we found
+ that writing before reading (in this case to an unused position)
+ seems to get rid of the problem */
+ __control_set_reg(wc,3,0x69); /* do magic here */
+ /* now get the read byte from the Xilinx part */
res = inb(wc->ioaddr + WC_USERREG + ((reg & 0xf) << 2));
return res;
}
@@ -290,6 +297,20 @@ static void __t1xxp_disable_interrupts(struct t1xxp *wc)
outb(0x00, wc->ioaddr + WC_MASK1);
}
+static void __t1xxp_set_clear(struct t1xxp *wc)
+{
+ /* Setup registers */
+ int x,y;
+ unsigned char b;
+ for (x=0;x<3;x++) {
+ b = 0;
+ 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);
+ }
+}
+
static void t1xxp_framer_start(struct t1xxp *wc)
{
int i;
@@ -327,6 +348,9 @@ static void t1xxp_framer_start(struct t1xxp *wc)
printk("Using %s/%s coding/framing\n", coding, framing);
if (!alreadyrunning) {
+ /* Setup the clear channels */
+ __t1xxp_set_clear(wc);
+
/* Set LIRST bit to 1 */
__t1_set_reg(wc, 0x0a, 0x80);
spin_unlock_irqrestore(&wc->lock, flags);
@@ -368,7 +392,7 @@ static int t1xxp_framer_hard_reset(struct t1xxp *wc)
spin_lock_irqsave(&wc->lock, flags);
/* Initialize all registers to 0 */
- for (x=0x0;x<0x96;x++)
+ for (x=0x0;x<192;x++)
__t1_set_reg(wc, x, 0);
/* Full-on sync required */
@@ -390,6 +414,7 @@ static int t1xxp_framer_hard_reset(struct t1xxp *wc)
__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;
}
@@ -442,10 +467,13 @@ static int t1xxp_ioctl(struct zt_chan *chan, unsigned int cmd, unsigned long dat
static int t1xxp_startup(struct zt_span *span)
{
struct t1xxp *wc = span->pvt;
+
+ int alreadyrunning = span->flags & ZT_FLAG_RUNNING;
/* Reset framer with proper parameters and start */
t1xxp_framer_start(wc);
+ printk("Calling startup (flags is %d)\n", span->flags);
- if (!(span->flags & ZT_FLAG_RUNNING)) {
+ if (!alreadyrunning) {
/* Only if we're not already going */
t1xxp_enable_interrupts(wc);
t1xxp_start_dma(wc);
@@ -475,20 +503,6 @@ static int t1xxp_maint(struct zt_span *span, int mode)
return -1;
}
-static void __t1xxp_set_clear(struct t1xxp *wc)
-{
- /* Setup registers */
- int x,y;
- unsigned char b;
- for (x=0;x<3;x++) {
- b = 0;
- 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);
- }
-}
-
static int t1xxp_chanconfig(struct zt_chan *chan, int sigtype)
{
struct t1xxp *wc = chan->pvt;
@@ -506,11 +520,13 @@ static int t1xxp_chanconfig(struct zt_chan *chan, int sigtype)
static int t1xxp_spanconfig(struct zt_span *span, struct zt_lineconfig *lc)
{
+ struct t1xxp *wc = span->pvt;
span->lineconfig = lc->lineconfig;
span->txlevel = lc->lbo;
span->rxlevel = 0;
/* Do we want to SYNC on receive or not */
- span->syncsrc = lc->sync;
+ span->syncsrc = 0;
+ wc->sync = lc->sync;
/* If already running, apply changes immediately */
if (span->flags & ZT_FLAG_RUNNING)
return t1xxp_startup(span);
@@ -553,7 +569,7 @@ static int t1xxp_software_init(struct t1xxp *wc)
wc->chans[x].sigcap = ZT_SIG_EM | ZT_SIG_CLEAR |
ZT_SIG_FXSLS | ZT_SIG_FXSGS |
ZT_SIG_FXSKS | ZT_SIG_FXOLS |
- ZT_SIG_FXOGS | ZT_SIG_FXOKS;
+ ZT_SIG_FXOGS | ZT_SIG_FXOKS | ZT_SIG_CAS;
wc->chans[x].pvt = wc;
wc->chans[x].chanpos = x + 1;
}
@@ -568,6 +584,7 @@ static inline void __handle_leds(struct t1xxp *wc)
{
int oldreg;
wc->blinktimer++;
+
if (wc->span.alarms & (ZT_ALARM_RED | ZT_ALARM_BLUE)) {
/* Red/Blue alarm */
#ifdef FANCY_ALARM
@@ -639,7 +656,7 @@ static void t1xxp_receiveprep(struct t1xxp *wc, int ints)
volatile unsigned char *rxbuf;
int x;
int y;
- if (ints & 0x08) {
+ if (ints & 0x04) {
/* Just received first buffer */
rxbuf = wc->readchunk;
} else {
@@ -663,6 +680,11 @@ static void t1xxp_receiveprep(struct t1xxp *wc, int ints)
rxbuf[32 * y + ((chanmap[x] + WC_OFFSET + wc->offset) & 0x1f)];
}
}
+ /* XXX We should apply echo cancellation closer -- we're wasting
+ 8 taps XXX */
+ for (x=0;x<24;x++)
+ zt_ec_chunk(&wc->chans[x], wc->chans[x].readchunk, wc->chans[x].writechunk);
+
zt_receive(&wc->span);
}
@@ -671,7 +693,7 @@ 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);
+ b = __t1_get_reg(wc, 0x63 + x);
for (y=0;y<8;y++) {
i = x * 8 + y;
rxs = 0;
@@ -688,7 +710,7 @@ static void __t1xxp_check_sigbits(struct t1xxp *wc, int x)
static void __t1xxp_check_alarms(struct t1xxp *wc)
{
- unsigned char c;
+ unsigned char c,d;
int alarms;
int x,j;
@@ -697,8 +719,8 @@ static void __t1xxp_check_alarms(struct t1xxp *wc)
wc->span.rxlevel = c >> 6;
/* Get status register s*/
- __t1_set_reg(wc, 0x20, 0xff);
- c = __t1_get_reg(wc, 0x20);
+ __t1_set_reg(wc, 0x20, 0xff);
+ c = __t1_get_reg(wc, 0x20);
/* Assume no alarms */
alarms = 0;
@@ -722,32 +744,50 @@ static void __t1xxp_check_alarms(struct t1xxp *wc)
alarms |= ZT_ALARM_BLUE;
/* Keep track of recovering */
- if (!alarms && wc->span.alarms)
+ 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) {
+ if (alarms && (!wc->span.alarms)) {
+#if 0
printk("Going into yellow alarm\n");
- __t1_set_reg(wc, 0x35, 0x11);
+#endif
+ __t1_set_reg(wc, 0x35, 0x11);
}
+ if (wc->span.alarms != alarms) {
+ d = __control_get_reg(wc, 0);
+ start_alarm(wc);
+ if (!(alarms & (ZT_ALARM_RED | ZT_ALARM_BLUE | ZT_ALARM_LOOPBACK)) &&
+ wc->sync) {
+ /* Use the recieve signalling */
+ wc->span.syncsrc = wc->span.spanno;
+ d |= 1;
+ } else {
+ wc->span.syncsrc = 0;
+ d &= ~1;
+ }
+ __control_set_reg(wc, 0, d);
+ }
+ if (wc->alarmtimer)
+ alarms |= ZT_ALARM_RECOVER;
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;
+ wc->span.alarms &= ~(ZT_ALARM_RECOVER);
/* Clear yellow alarm */
- printk("Coming out of yellow alarm\n");
+#if 0
+ printk("Coming out of alarm\n");
+#endif
__t1_set_reg(wc, 0x35, 0x10);
zt_alarm_notify(&wc->span);
}
@@ -777,7 +817,9 @@ static void t1xxp_interrupt(int irq, void *dev_id, struct pt_regs *regs)
}
spin_lock_irqsave(&wc->lock, flags);
+#if 1
__handle_leds(wc);
+#endif
/* Count down timers */
__t1xxp_do_counters(wc);
@@ -788,10 +830,7 @@ static void t1xxp_interrupt(int irq, void *dev_id, struct pt_regs *regs)
case 0:
case 1:
case 2:
- case 3:
-#if 0
__t1xxp_check_sigbits(wc, x);
-#endif
break;
case 4:
__t1xxp_check_alarms(wc);
@@ -902,7 +941,7 @@ static int __devinit t1xxp_init_one(struct pci_dev *pdev, const struct pci_devic
/* Keep track of which device we are */
pci_set_drvdata(pdev, wc);
- if (request_irq(pdev->irq, t1xxp_interrupt, SA_SHIRQ, "t1xxp", wc)) {
+ if (request_irq(pdev->irq, t1xxp_interrupt, SA_INTERRUPT | SA_SHIRQ, "t1xxp", wc)) {
printk("t1xxp: Unable to request IRQ %d\n", pdev->irq);
kfree(wc);
return -EIO;