summaryrefslogtreecommitdiff
path: root/wct1xxp.c
diff options
context:
space:
mode:
authormarkster <markster@5390a7c7-147a-4af0-8ec9-7488f05a26cb>2001-12-05 18:38:19 +0000
committermarkster <markster@5390a7c7-147a-4af0-8ec9-7488f05a26cb>2001-12-05 18:38:19 +0000
commit07d2942df868bbed234e7c7c3c23ba7356c977f4 (patch)
tree410041528d87b3f173d39e16a86bc4b6a977b4e2 /wct1xxp.c
parent021d482685b38bddbb3cf3b282363a657e072be5 (diff)
Version 0.1.4 from FTP
git-svn-id: http://svn.digium.com/svn/zaptel/trunk@34 5390a7c7-147a-4af0-8ec9-7488f05a26cb
Diffstat (limited to 'wct1xxp.c')
-rwxr-xr-xwct1xxp.c569
1 files changed, 422 insertions, 147 deletions
diff --git a/wct1xxp.c b/wct1xxp.c
index a173941..82a634c 100755
--- a/wct1xxp.c
+++ b/wct1xxp.c
@@ -32,13 +32,23 @@
#include <linux/usb.h>
#include <linux/errno.h>
#include <linux/pci.h>
+#include <linux/spinlock.h>
#ifdef STANDALONE_ZAPATA
#include "zaptel.h"
#else
#include <linux/zaptel.h>
#endif
-#define DELAY 0x30 /* 30 = 15 cycles, 10 = 8 cycles, 0 = 3 cycles */
+#define WC_MAX_CARDS 32
+
+#define TEST_REGS
+
+/* Define to get more attention-grabbing but slightly more I/O using
+ alarm status */
+#define FANCY_ALARM
+
+
+#define DELAY 0x0 /* 30 = 15 cycles, 10 = 8 cycles, 0 = 3 cycles */
#define WC_CNTL 0x00
#define WC_OPER 0x01
@@ -68,7 +78,7 @@
/* Offset between transmit and receive */
#define WC_OFFSET 4
-#define BIT_CS (1 << 5)
+#define BIT_CS (1 << 7)
#define BIT_OK (1 << 0)
#define BIT_TEST (1 << 1)
@@ -76,26 +86,41 @@
#define BIT_ALARM (1 << 3)
static int chanmap[] =
-{ 1,2,3,
- 5,6,7,
- 9,10,11,
- 13,14,15,
- 17,18,19,
- 21,22,23,
- 25,26,27,
- 29,30,31 };
+{ 2,1,0,
+ 6,5,4,
+ 10,9,8,
+ 14,13,12,
+ 18,17,16,
+ 22,21,20,
+ 26,25,24,
+ 30,29,28 };
+
+#ifdef FANCY_ALARM
+static int altab[] = {
+0, 0, 0, 1, 2, 3, 4, 6, 8, 9, 11, 13, 16, 18, 20, 22, 24, 25, 27, 28, 29, 30, 31, 31, 32, 31, 31, 30, 29, 28, 27, 25, 23, 22, 20, 18, 16, 13, 11, 9, 8, 6, 4, 3, 2, 1, 0, 0,
+};
+#endif
struct t1xxp {
struct pci_dev *dev;
+ spinlock_t lock;
+ int num;
+ /* Our offset for finding channel 1 */
+ int offset;
char *variety;
int usecount;
int dead;
int alarmtimer;
int alarm;
- int alarmthreshold;
+ int alreadyrunning;
+#ifdef FANCY_ALARM
+ int alarmpos;
+#endif
unsigned char ledtestreg;
unsigned char outbyte;
unsigned long ioaddr;
+ unsigned char txsiga[3];
+ unsigned char txsigb[3];
dma_addr_t readdma;
dma_addr_t writedma;
volatile unsigned char *writechunk; /* Double-word aligned write memory */
@@ -104,6 +129,26 @@ struct t1xxp {
struct zt_chan chans[24]; /* Channels */
};
+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;
+}
+
+static inline void stop_alarm(struct t1xxp *wc)
+{
+ wc->alarm = 0;
+#ifdef FANCY_ALARM
+ wc->alarmpos = 0;
+#endif
+ wc->alarmtimer = 0;
+}
+
static inline void select_framer(struct t1xxp *wc)
{
if (wc->outbyte & BIT_CS) {
@@ -120,23 +165,6 @@ static inline void select_control(struct t1xxp *wc)
}
}
-static inline void select_page(struct t1xxp *wc, unsigned char reg)
-{
- int page = (reg & 0x30) << 2;
- if (wc->outbyte != page) {
- /* Clear high bits */
- wc->outbyte &= 0x3f;
- /* Set page */
- wc->outbyte |= page;
- /* Make sure we've turned on the framer */
- wc->outbyte &= ~BIT_CS;
- outb(wc->outbyte, wc->ioaddr + WC_AUXD);
- } else if (wc->outbyte & BIT_CS) {
- /* Check to be sure we don't still have to enable the framer */
- select_framer(wc);
- }
-}
-
static int t1xxp_open(struct zt_chan *chan)
{
struct t1xxp *wc = chan->pvt;
@@ -150,15 +178,20 @@ static int t1xxp_open(struct zt_chan *chan)
static int t1_get_reg(struct t1xxp *wc, int reg)
{
unsigned char res;
- select_page(wc, reg);
- res = inb(wc->ioaddr + WC_USERREG + ((reg & 0xf) << 2));
+ select_framer(wc);
+ /* Send address */
+ outb(reg & 0xff, wc->ioaddr + WC_USERREG + 4);
+ /* Get value */
+ res = inb(wc->ioaddr + WC_USERREG);
return res;
}
static int t1_set_reg(struct t1xxp *wc, int reg, unsigned char val)
{
- select_page(wc, reg);
- outb(val, wc->ioaddr + WC_USERREG + ((reg & 0xf) << 2));
+ select_framer(wc);
+ /* Send address */
+ outb(reg & 0xff, wc->ioaddr + WC_USERREG + 4);
+ outb(val, wc->ioaddr + WC_USERREG);
return 0;
}
@@ -179,6 +212,7 @@ static int control_get_reg(struct t1xxp *wc, int reg)
static void t1xxp_release(struct t1xxp *wc)
{
+ zt_unregister(&wc->span);
kfree(wc);
printk("Freed a Wildcard\n");
}
@@ -194,19 +228,314 @@ static int t1xxp_close(struct zt_chan *chan)
return 0;
}
+static void t1xxp_enable_interrupts(struct t1xxp *wc)
+{
+ /* Clear interrupts */
+ outb(0xff, wc->ioaddr + WC_INTSTAT);
+ /* Enable interrupts (we care about all of them) */
+ outb(0x3f, wc->ioaddr + WC_MASK0);
+ /* No external interrupts */
+ outb(0x00, wc->ioaddr + WC_MASK1);
+}
+
+static void t1xxp_start_dma(struct t1xxp *wc)
+{
+ /* Reset Master and TDM */
+ outb(DELAY | 0x0f, wc->ioaddr + WC_CNTL);
+ set_current_state(TASK_INTERRUPTIBLE);
+ schedule_timeout(1);
+ outb(DELAY | 0x01, wc->ioaddr + WC_CNTL);
+ outb(0x01, wc->ioaddr + WC_OPER);
+ printk("Started DMA\n");
+}
+
+static void t1xxp_stop_dma(struct t1xxp *wc)
+{
+ outb(0x00, wc->ioaddr + WC_OPER);
+}
+
+static void t1xxp_disable_interrupts(struct t1xxp *wc)
+{
+ outb(0x00, wc->ioaddr + WC_MASK0);
+ outb(0x00, wc->ioaddr + WC_MASK1);
+}
+
+static void t1xxp_framer_start(struct t1xxp *wc)
+{
+ int i;
+ char *coding, *framing;
+ unsigned long endjiffies;
+ /* Build up config */
+ i = 0x20;
+ if (wc->span.lineconfig & ZT_CONFIG_ESF) {
+ coding = "ESF";
+ i = 0x88;
+ } else {
+ coding = "SF";
+ }
+ if (wc->span.lineconfig & ZT_CONFIG_B8ZS) {
+ framing = "B8ZS";
+ i |= 0x44;
+ } else {
+ framing = "AMI";
+ }
+ t1_set_reg(wc, 0x38, i);
+ if (!(wc->span.lineconfig & ZT_CONFIG_ESF)) {
+ /* 1c in FDL bit */
+ t1_set_reg(wc, 0x7e, 0x1c);
+ } else {
+ t1_set_reg(wc, 0x7e, 0x00);
+ }
+
+ /* Set outgoing LBO */
+ t1_set_reg(wc, 0x7c, wc->span.txlevel << 5);
+
+ printk("Using %s/%s coding/framing\n", coding, framing);
+ if (!wc->alreadyrunning) {
+ /* Set LIRST bit to 1 */
+ t1_set_reg(wc, 0x30, 0x1);
+
+ /* 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);
+ }
+ }
+#endif
+}
+
+static int t1xxp_framer_hard_reset(struct t1xxp *wc)
+{
+ int x;
+ /* 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);
+
+ /* Full-on sync required */
+ t1_set_reg(wc, 0x2b, 0x08);
+
+ /* RSYNC is an input */
+ t1_set_reg(wc, 0x2c, 0x08);
+
+ /* Enable tx RBS bits */
+ t1_set_reg(wc, 0x35, 0x10);
+
+ /* TSYNC is output */
+ 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
+ return 0;
+}
+
+static int t1xxp_rbsbits(struct zt_chan *chan, int bits)
+{
+ struct t1xxp *wc = chan->pvt;
+ /* Byte offset */
+ int b = (chan->chanpos - 1) / 8;
+ int o = (chan->chanpos - 1) % 8;
+ unsigned char mask = (1 << o);
+ if (bits & ZT_ABIT) {
+ /* Set A-bit */
+ wc->txsiga[b] |= mask;
+ } else {
+ /* Clear A-bit */
+ wc->txsiga[b] &= ~mask;
+ }
+ if (bits & ZT_BBIT) {
+ /* Set B-bit */
+ wc->txsigb[b] |= mask;
+ } else {
+ 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]);
+ return 0;
+}
+
+static int t1xxp_ioctl(struct zt_chan *chan, unsigned int cmd, unsigned long data)
+{
+ switch(cmd) {
+ default:
+ return -ENOTTY;
+ }
+}
+
+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);
+ t1xxp_start_dma(wc);
+ span->flags |= ZT_FLAG_RUNNING;
+ }
+ return 0;
+}
+
+static int t1xxp_shutdown(struct zt_span *span)
+{
+ struct t1xxp *wc = span->pvt;
+ t1xxp_stop_dma(wc);
+ t1xxp_disable_interrupts(wc);
+ span->flags &= ~ZT_FLAG_RUNNING;
+ return 0;
+}
+
+static int t1xxp_maint(struct zt_span *span, int mode)
+{
+ /* XXX Implement me XXX */
+ 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;
+ int flags;
+ int alreadyrunning = chan->span->flags & ZT_FLAG_RUNNING;
+ spin_lock_irqsave(&wc->lock, flags);
+ if (alreadyrunning)
+ t1xxp_set_clear(wc);
+ spin_unlock_irqrestore(&wc->lock, flags);
+ return 0;
+}
+
+static int t1xxp_spanconfig(struct zt_span *span, struct zt_lineconfig *lc)
+{
+ span->lineconfig = lc->lineconfig;
+ span->txlevel = lc->lbo;
+ span->rxlevel = 0;
+ /* Do we want to SYNC on receive or not */
+ span->syncsrc = lc->sync;
+ /* If already running, apply changes immediately */
+ if (span->flags & ZT_FLAG_RUNNING)
+ return t1xxp_startup(span);
+ return 0;
+}
+
+static int t1xxp_software_init(struct t1xxp *wc)
+{
+ int x;
+ /* Find position */
+ for (x=0;x<WC_MAX_CARDS;x++) {
+ if (!cards[x]) {
+ cards[x] = wc;
+ break;
+ }
+ }
+ if (x >= WC_MAX_CARDS)
+ return -1;
+ wc->num = x;
+ sprintf(wc->span.name, "WCT1/%d", wc->num);
+ sprintf(wc->span.desc, "%s card %d", wc->variety, wc->num);
+ wc->span.spanconfig = t1xxp_spanconfig;
+ wc->span.chanconfig = t1xxp_chanconfig;
+ wc->span.startup = t1xxp_startup;
+ wc->span.shutdown = t1xxp_shutdown;
+ wc->span.rbsbits = t1xxp_rbsbits;
+ wc->span.maint = t1xxp_maint;
+ wc->span.open = t1xxp_open;
+ wc->span.close = t1xxp_close;
+ wc->span.channels = 24;
+ wc->span.chans = wc->chans;
+ wc->span.flags = ZT_FLAG_RBS;
+ wc->span.linecompat = ZT_CONFIG_AMI | ZT_CONFIG_B8ZS | ZT_CONFIG_D4 | ZT_CONFIG_ESF;
+ wc->span.ioctl = t1xxp_ioctl;
+ wc->span.pvt = wc;
+ init_waitqueue_head(&wc->span.maintq);
+ for (x=0;x<24;x++) {
+ sprintf(wc->chans[x].name, "WCT1/%d/%d", wc->num, x + 1);
+ 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;
+ wc->chans[x].pvt = wc;
+ wc->chans[x].chanpos = x + 1;
+ }
+ if (zt_register(&wc->span, 0)) {
+ printk("Unable to register span with zaptel\n");
+ return -1;
+ }
+ return 0;
+}
+
static inline void handle_leds(struct t1xxp *wc)
{
if (wc->alarm) {
#ifdef FANCY_ALARM
- if (wc->alarmtimer == wc->alarmthreshold << 1) {
- wc->ledtestreg = wc->ledtestreg & ~BIT_ALARM;
+ if (wc->alarmtimer == (altab[wc->alarmpos] >> 1)) {
+ wc->ledtestreg = wc->ledtestreg | BIT_ALARM;
control_set_reg(wc, WC_LEDTEST, wc->ledtestreg);
}
- if (wc->alarmtimer == 0x1f) {
- wc->ledtestreg = wc->ledtestreg | BIT_ALARM;
+ if (wc->alarmtimer == 0xf) {
+ wc->ledtestreg = wc->ledtestreg & ~BIT_ALARM;
control_set_reg(wc, WC_LEDTEST, wc->ledtestreg);
wc->alarmtimer = -1;
- wc->alarmthreshold = (wc->alarmthreshold + 1 & 0x1f);
+ wc->alarmpos++;
+ if (wc->alarmpos >= (sizeof(altab) / sizeof(altab[0])))
+ wc->alarmpos = 0;
}
wc->alarmtimer++;
#else
@@ -235,10 +564,12 @@ static void t1xxp_transmitprep(struct t1xxp *wc, int ints)
/* Just finished sending second buffer, fill it now */
txbuf = wc->writechunk + 32 * ZT_CHUNKSIZE;
}
+ zt_transmit(&wc->span);
for (y=0;y<ZT_CHUNKSIZE;y++) {
for (x=0;x<24;x++) {
/* Put channel number as outgoing data */
- txbuf[y * 32 + chanmap[x]] = (unsigned char)x;
+ txbuf[y * 32 + ((chanmap[x] + wc->offset) & 0x1f)] =
+ wc->chans[x].writechunk[y];
}
}
}
@@ -246,47 +577,78 @@ static void t1xxp_transmitprep(struct t1xxp *wc, int ints)
static void t1xxp_receiveprep(struct t1xxp *wc, int ints)
{
volatile unsigned char *rxbuf;
- static int looper=0;
int x;
- unsigned char tmpbuf[32];
+ int y;
if (ints & 0x08) {
/* Just received first buffer */
rxbuf = wc->readchunk;
} else {
rxbuf = wc->readchunk + ZT_CHUNKSIZE * 32;
}
- for (x=0;x<24;x++) {
- /* Must map received channels into appropriate data */
- tmpbuf[x] = rxbuf[(chanmap[x] + WC_OFFSET) & 0x1f];
+ for (x=3;x<32;x+=4) {
+ if (rxbuf[(x + WC_OFFSET) & 0x1f] == 0x7f) {
+ if (wc->offset != (x-3)) {
+ wc->offset = x - 3;
+#if 1
+ printk("New offset: %d\n", wc->offset);
+#endif
+ }
+ }
}
- if (!(looper++ % 1000)) {
- memcpy(tmpbuf, rxbuf, 32);
- for (x=0;x<24;x++)
- printk("%d: %d\n", x, (int)tmpbuf[x]);
+ for (y=0;y<ZT_CHUNKSIZE;y++) {
+ for (x=0;x<24;x++) {
+ /* XXX Optimize, remove * and + XXX */
+ /* Must map received channels into appropriate data */
+ wc->chans[x].readchunk[y] =
+ rxbuf[32 * y + ((chanmap[x] + WC_OFFSET + wc->offset) & 0x1f)];
+ }
}
-
+ zt_receive(&wc->span);
}
static void t1xxp_interrupt(int irq, void *dev_id, struct pt_regs *regs)
{
struct t1xxp *wc = dev_id;
- unsigned char ints;
- unsigned char b;
+ unsigned char ints, a,b, rxs;
static int gotint = 0;
+ int x,y,i;
ints = inb(wc->ioaddr + WC_INTSTAT);
+ if (!ints)
+ return;
+
outb(ints, wc->ioaddr + WC_INTSTAT);
if (!gotint) {
printk("Got interrupt: 0x%04x\n", ints);
- gotint++;
}
+ gotint++;
if (ints & 0x0f) {
t1xxp_transmitprep(wc, ints);
t1xxp_receiveprep(wc, ints);
}
handle_leds(wc);
-
+#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);
+ }
+ }
+ }
+ }
+#endif
if (ints & 0x10)
printk("PCI Master abort\n");
@@ -296,30 +658,8 @@ static void t1xxp_interrupt(int irq, void *dev_id, struct pt_regs *regs)
}
-static int t1xxp_reset(struct t1xxp *wc)
-{
- char c;
- c = t1_get_reg(wc, 0x30);
- /* Reset the Line Interface */
- t1_set_reg(wc, 0x30, c | 0x1);
-
- /* Wait 50ms for this to finish */
- mdelay(50);
-
- /* Clear it */
- t1_set_reg(wc, 0x30, c);
-
- /* Reset the elastic stores */
- t1_set_reg(wc, 0x30, c | 0x40);
- mdelay(1);
- t1_set_reg(wc, 0x30, c);
-
- return 0;
-}
-
static int t1xxp_hardware_init(struct t1xxp *wc)
{
- int x;
/* Hardware PCI stuff */
/* Reset chip and registers */
outb(DELAY | 0x0e, wc->ioaddr + WC_CNTL);
@@ -354,83 +694,21 @@ static int t1xxp_hardware_init(struct t1xxp *wc)
/* Second frame */
outl(wc->readdma + ZT_CHUNKSIZE * 32 * 2 - 4, wc->ioaddr + WC_DMARE); /* End */
- printk("Setting up DMA (write/read = %08lx/%08lx)\n", wc->writedma, wc->readdma);
-
- /* Clear interrupts */
- outb(0xff, wc->ioaddr + WC_INTSTAT);
+ printk("Setting up DMA (write/read = %08x/%08x)\n", wc->writedma, wc->readdma);
/* 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);
+
+ /* Reset the T1 and report */
+ t1xxp_framer_hard_reset(wc);
/* Pretend we're in alarm */
- wc->alarm = 1;
+ start_alarm(wc);
return 0;
-#if 0
- /* Reset all registers on the 2151 */
- for (x=0x20;x<0x40;x++)
- t1_set_reg(wc, x, 0);
- for (x=0x60;x<0x80;x++)
- t1_set_reg(wc, x, 0);
- /* Sanity check the T1 */
- if (t1_get_reg(wc, 0x7c) != 0) {
- printk("Unable to talk to T1 part\n");
- return -ENOSYS;
- }
- /* Enable elastic store for transmit and receive,
- 2.048 Mhz bus */
- t1_set_reg(wc, 0x37, 0x8c | 0x01);
-
- /* TSync is an output */
- t1_set_reg(wc, 0x36, 0x04);
-
- /* RSync is an input (Elastic Store) */
- t1_set_reg(wc, 0x2c, 0x08);
-
- /* ESF/B8ZS */
- t1_set_reg(wc, 0x38, 0xcc);
- {
- /* XXX Take me out XXX */
- t1_set_reg(wc, 0x2d, 0xff);
- t1_set_reg(wc, 0x2e, 0xff);
- t1_set_reg(wc, 0x2f, 0xff);
- }
- return t1xxp_reset(wc);
-#endif
}
-static void t1xxp_enable_interrupts(struct t1xxp *wc)
-{
- /* Enable interrupts (we care about all of them) */
- outb(0x3f, wc->ioaddr + WC_MASK0);
- /* No external interrupts */
- outb(0x00, wc->ioaddr + WC_MASK1);
-}
-
-static void t1xxp_start_dma(struct t1xxp *wc)
-{
- /* Reset Master and TDM */
- outb(DELAY | 0x0f, wc->ioaddr + WC_CNTL);
- set_current_state(TASK_INTERRUPTIBLE);
- schedule_timeout(1);
- outb(DELAY | 0x01, wc->ioaddr + WC_CNTL);
- outb(0x01, wc->ioaddr + WC_OPER);
- printk("Started DMA\n");
-}
-
-static void t1xxp_stop_dma(struct t1xxp *wc)
-{
- outb(0x00, wc->ioaddr + WC_OPER);
-}
-
-static void t1xxp_disable_interrupts(struct t1xxp *wc)
-{
- outb(0x00, wc->ioaddr + WC_MASK0);
- outb(0x00, wc->ioaddr + WC_MASK1);
-}
-
-
static int __devinit t1xxp_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
{
int res;
@@ -474,14 +752,11 @@ static int __devinit t1xxp_init_one(struct pci_dev *pdev, const struct pci_devic
kfree(wc);
return -EIO;
}
-
-
+ /* Initialize hardware */
t1xxp_hardware_init(wc);
- /* Enable interrupts */
- t1xxp_enable_interrupts(wc);
- /* Start DMA */
- t1xxp_start_dma(wc);
+ /* Misc. software stuff */
+ t1xxp_software_init(wc);
printk("Found a Wildcard: %s\n", wc->variety);
res = 0;