summaryrefslogtreecommitdiff
path: root/wctdm24xxp.c
diff options
context:
space:
mode:
authormattf <mattf@5390a7c7-147a-4af0-8ec9-7488f05a26cb>2007-01-25 22:17:16 +0000
committermattf <mattf@5390a7c7-147a-4af0-8ec9-7488f05a26cb>2007-01-25 22:17:16 +0000
commitf62ab473d3692e18d3c189908cd3c85a2ed44c08 (patch)
tree657fb6891973edf085afef12cddbef1c77222ab9 /wctdm24xxp.c
parent4064ee33062608cb774beae383e27761705e5122 (diff)
Add additional product support.
git-svn-id: http://svn.digium.com/svn/zaptel/branches/1.4@1969 5390a7c7-147a-4af0-8ec9-7488f05a26cb
Diffstat (limited to 'wctdm24xxp.c')
-rw-r--r--wctdm24xxp.c145
1 files changed, 97 insertions, 48 deletions
diff --git a/wctdm24xxp.c b/wctdm24xxp.c
index 031f139..e6890de 100644
--- a/wctdm24xxp.c
+++ b/wctdm24xxp.c
@@ -2,6 +2,8 @@
* Wilcard TDM2400P TDM FXS/FXO Interface Driver for Zapata Telephony interface
*
* Written by Mark Spencer <markster@digium.com>
+ * Further modified to add support for the TDM800P by Matthew Fredrickson <creslin@digium.com>
+ *
* Copyright (C) 2005,2006, Digium, Inc.
* All rights reserved.
*
@@ -43,7 +45,7 @@ Tx Gain - W/Pre-Emphasis: -23.99 to 0.00 db
#include "wctdm.h"
/* Comment to disable VPM support */
-#define VPM_SUPPORT
+/* #define VPM_SUPPORT */
#ifdef VPM_SUPPORT
@@ -300,9 +302,9 @@ static struct fxo_mode {
#define CMD_WR(a,b) (((a) << 8) | (b) | __CMD_WR)
#define CMD_RD(a) (((a) << 8) | __CMD_RD)
-#define CMD_BYTE(card,bit) (((((card) & 0x3) * 3 + (bit)) * 7) \
- + ((card) >> 2))
+#define CMD_BYTE(card,bit,altcs) (((((card) & 0x3) * 3 + (bit)) * 7) \
+ + ((card) >> 2) + (altcs) + ((altcs) ? -21 : 0))
struct calregs {
unsigned char vals[NUM_CAL_REGS];
@@ -337,6 +339,7 @@ struct wctdm {
unsigned char ctlreg;
int cards;
int cardflag; /* Bit-map of present cards */
+ int altcs[NUM_CARDS + NUM_EC];
char qrvhook[NUM_CARDS];
unsigned short qrvdebtime[NUM_CARDS];
int radmode[NUM_CARDS];
@@ -383,6 +386,7 @@ struct wctdm {
/* Set hook */
int sethook[NUM_CARDS + NUM_EC];
int dacssrc[NUM_CARDS];
+ int type;
#ifdef VPM_SUPPORT
int vpm;
@@ -410,9 +414,11 @@ struct wctdm {
struct wctdm_desc {
char *name;
int flags;
+ int ports;
};
-static struct wctdm_desc wctdm = { "Wildcard TDM2400P", 0 };
+static struct wctdm_desc wctdm2400 = { "TDM2400P", 0, 24 };
+static struct wctdm_desc wctdm800 = { "TDM800P", 0, 8 };
static int acim2tiss[16] = { 0x0, 0x1, 0x4, 0x5, 0x7, 0x0, 0x0, 0x6, 0x0, 0x0, 0x0, 0x2, 0x0, 0x3 };
static struct wctdm *ifaces[WC_MAX_IFACES];
@@ -445,6 +451,19 @@ static int dtmfthreshold = VPM_DEFAULT_DTMFTHRESHOLD;
static int wctdm_init_proslic(struct wctdm *wc, int card, int fast , int manual, int sane);
+#if 0
+static inline int CMD_BYTE(int card,int bit,int altcs)
+{
+ int res;
+ res = (((((card) & 0x3) * 3 + (bit)) * 7) \
+ + ((card) >> 2) + (altcs));
+ //+ ((card) >> 2) + (altcs) + (altcs ? 42 : 0));
+ if (((res == 31) || (res == 24) || (res == 38)) && (card != 5))
+ printk("%d %d %d\n", card, bit, altcs);
+ return res;
+}
+#endif
+
/* sleep in user space until woken up. Equivilant of tsleep() in BSD */
static int schluffen(wait_queue_head_t *q)
{
@@ -473,6 +492,7 @@ static inline void cmd_dequeue(struct wctdm *wc, volatile unsigned char *writech
unsigned long flags;
unsigned int curcmd=0;
int x;
+ int subaddr = card & 0x3;
#ifdef FANCY_ECHOCAN
int ecval;
ecval = wc->echocanpos;
@@ -485,6 +505,9 @@ static inline void cmd_dequeue(struct wctdm *wc, volatile unsigned char *writech
{
return;
}
+ if (wc->altcs[card])
+ subaddr = 0;
+
/* Skip audio */
writechunk += 24;
spin_lock_irqsave(&wc->reglock, flags);
@@ -522,59 +545,59 @@ static inline void cmd_dequeue(struct wctdm *wc, volatile unsigned char *writech
}
}
if (wc->modtype[card] == MOD_TYPE_FXS) {
- writechunk[CMD_BYTE(card, 0)] = (1 << (card & 0x3));
+ writechunk[CMD_BYTE(card, 0, wc->altcs[card])] = (1 << (subaddr));
if (curcmd & __CMD_WR)
- writechunk[CMD_BYTE(card, 1)] = (curcmd >> 8) & 0x7f;
+ writechunk[CMD_BYTE(card, 1, wc->altcs[card])] = (curcmd >> 8) & 0x7f;
else
- writechunk[CMD_BYTE(card, 1)] = 0x80 | ((curcmd >> 8) & 0x7f);
- writechunk[CMD_BYTE(card, 2)] = curcmd & 0xff;
+ writechunk[CMD_BYTE(card, 1, wc->altcs[card])] = 0x80 | ((curcmd >> 8) & 0x7f);
+ writechunk[CMD_BYTE(card, 2, wc->altcs[card])] = curcmd & 0xff;
} else if (wc->modtype[card] == MOD_TYPE_FXO) {
if (curcmd & __CMD_WR)
- writechunk[CMD_BYTE(card, 0)] = 0x20 | fxo_addrs[card & 0x3];
+ writechunk[CMD_BYTE(card, 0, wc->altcs[card])] = 0x20 | fxo_addrs[subaddr];
else
- writechunk[CMD_BYTE(card, 0)] = 0x60 | fxo_addrs[card & 0x3];
- writechunk[CMD_BYTE(card, 1)] = (curcmd >> 8) & 0xff;
- writechunk[CMD_BYTE(card, 2)] = curcmd & 0xff;
+ writechunk[CMD_BYTE(card, 0, wc->altcs[card])] = 0x60 | fxo_addrs[subaddr];
+ writechunk[CMD_BYTE(card, 1, wc->altcs[card])] = (curcmd >> 8) & 0xff;
+ writechunk[CMD_BYTE(card, 2, wc->altcs[card])] = curcmd & 0xff;
} else if (wc->modtype[card] == MOD_TYPE_FXSINIT) {
/* Special case, we initialize the FXS's into the three-byte command mode then
switch to the regular mode. To send it into thee byte mode, treat the path as
6 two-byte commands and in the last one we initialize register 0 to 0x80. All modules
read this as the command to switch to daisy chain mode and we're done. */
- writechunk[CMD_BYTE(card, 0)] = 0x00;
- writechunk[CMD_BYTE(card, 1)] = 0x00;
+ writechunk[CMD_BYTE(card, 0, wc->altcs[card])] = 0x00;
+ writechunk[CMD_BYTE(card, 1, wc->altcs[card])] = 0x00;
if ((card & 0x1) == 0x1)
- writechunk[CMD_BYTE(card, 2)] = 0x80;
+ writechunk[CMD_BYTE(card, 2, wc->altcs[card])] = 0x80;
else
- writechunk[CMD_BYTE(card, 2)] = 0x00;
+ writechunk[CMD_BYTE(card, 2, wc->altcs[card])] = 0x00;
#ifdef VPM_SUPPORT
} else if (wc->modtype[card] == MOD_TYPE_VPM) {
if (curcmd & __CMD_WR)
- writechunk[CMD_BYTE(card, 0)] = ((card & 0x3) << 4) | 0xc | ((curcmd >> 16) & 0x1);
+ writechunk[CMD_BYTE(card, 0, wc->altcs[card])] = ((card & 0x3) << 4) | 0xc | ((curcmd >> 16) & 0x1);
else
- writechunk[CMD_BYTE(card, 0)] = ((card & 0x3) << 4) | 0xa | ((curcmd >> 16) & 0x1);
- writechunk[CMD_BYTE(card, 1)] = (curcmd >> 8) & 0xff;
- writechunk[CMD_BYTE(card, 2)] = curcmd & 0xff;
+ writechunk[CMD_BYTE(card, 0, wc->altcs[card])] = ((card & 0x3) << 4) | 0xa | ((curcmd >> 16) & 0x1);
+ writechunk[CMD_BYTE(card, 1, wc->altcs[card])] = (curcmd >> 8) & 0xff;
+ writechunk[CMD_BYTE(card, 2, wc->altcs[card])] = curcmd & 0xff;
#endif
} else if (wc->modtype[card] == MOD_TYPE_QRV) {
- writechunk[CMD_BYTE(card, 0)] = 0x00;
+ writechunk[CMD_BYTE(card, 0, wc->altcs[card])] = 0x00;
if (!curcmd)
{
- writechunk[CMD_BYTE(card, 1)] = 0x00;
- writechunk[CMD_BYTE(card, 2)] = 0x00;
+ writechunk[CMD_BYTE(card, 1, wc->altcs[card])] = 0x00;
+ writechunk[CMD_BYTE(card, 2, wc->altcs[card])] = 0x00;
}
else
{
if (curcmd & __CMD_WR)
- writechunk[CMD_BYTE(card, 1)] = 0x40 | ((curcmd >> 8) & 0x3f);
+ writechunk[CMD_BYTE(card, 1, wc->altcs[card])] = 0x40 | ((curcmd >> 8) & 0x3f);
else
- writechunk[CMD_BYTE(card, 1)] = 0xc0 | ((curcmd >> 8) & 0x3f);
- writechunk[CMD_BYTE(card, 2)] = curcmd & 0xff;
+ writechunk[CMD_BYTE(card, 1, wc->altcs[card])] = 0xc0 | ((curcmd >> 8) & 0x3f);
+ writechunk[CMD_BYTE(card, 2, wc->altcs[card])] = curcmd & 0xff;
}
} else if (wc->modtype[card] == MOD_TYPE_NONE) {
- writechunk[CMD_BYTE(card, 0)] = 0x00;
- writechunk[CMD_BYTE(card, 1)] = 0x00;
- writechunk[CMD_BYTE(card, 2)] = 0x00;
+ writechunk[CMD_BYTE(card, 0, wc->altcs[card])] = 0x00;
+ writechunk[CMD_BYTE(card, 1, wc->altcs[card])] = 0x00;
+ writechunk[CMD_BYTE(card, 2, wc->altcs[card])] = 0x00;
}
#if 0
/* XXX */
@@ -610,7 +633,7 @@ static inline void cmd_decifer(struct wctdm *wc, volatile unsigned char *readchu
ident = (wc->cmdq[card].cmds[x] >> 24) & 0xff;
if (ident == wc->rxident) {
/* Store result */
- wc->cmdq[card].cmds[x] |= readchunk[CMD_BYTE(card, 2)];
+ wc->cmdq[card].cmds[x] |= readchunk[CMD_BYTE(card, 2, wc->altcs[card])];
wc->cmdq[card].cmds[x] |= __CMD_FIN;
if (wc->cmdq[card].cmds[x] & __CMD_WR) {
/* Go ahead and clear out writes since they need no acknowledgement */
@@ -686,9 +709,10 @@ static inline void wctdm_transmitprep(struct wctdm *wc, int dbl)
for (x=0;x<ZT_CHUNKSIZE;x++) {
/* Send a sample, as a 32-bit word */
- for (y=0;y < wc->cards;y++) {
+ for (y=0;y < wc->type;y++) {
if (!x)
cmd_checkisr(wc, y);
+
writechunk[y] = wc->chans[y].writechunk[x];
cmd_dequeue(wc, writechunk, y, x);
}
@@ -951,7 +975,7 @@ static inline void wctdm_receiveprep(struct wctdm *wc, int dbl)
cmd_retransmit(wc);
}
}
- for (y=0;y < wc->cards;y++) {
+ for (y=0;y < wc->type;y++) {
wc->chans[y].readchunk[x] = readchunk[y];
cmd_decifer(wc, readchunk, y);
}
@@ -969,7 +993,7 @@ static inline void wctdm_receiveprep(struct wctdm *wc, int dbl)
readchunk += (EFRAME_SIZE + EFRAME_GAP);
}
/* XXX We're wasting 8 taps. We should get closer :( */
- for (x=0;x<wc->cards;x++) {
+ for (x=0;x<wc->type;x++) {
if (wc->cardflag & (1 << x))
zt_ec_chunk(&wc->chans[x], wc->chans[x].readchunk, wc->chans[x].writechunk);
}
@@ -1714,7 +1738,7 @@ static int wctdm_powerup_proslic(struct wctdm *wc, int card, int fast)
}
if (vbat < 0xc0) {
- printk("ProSLIC on module %d failed to powerup within %d ms (%d mV only)\n\n -- DID YOU REMEMBER TO PLUG IN THE HD POWER CABLE TO THE TDM2400P??\n",
+ printk("ProSLIC on module %d failed to powerup within %d ms (%d mV only)\n\n -- DID YOU REMEMBER TO PLUG IN THE HD POWER CABLE TO THE TDM CARD??\n",
card, (int)(((jiffies - origjiffies) * 1000 / HZ)),
vbat * 375);
return -1;
@@ -2910,7 +2934,7 @@ static int wctdm_initialize(struct wctdm *wc)
wc->chans[x].pvt = wc;
}
wc->span.chans = wc->chans;
- wc->span.channels = wc->cards;
+ wc->span.channels = wc->type;
wc->span.hooksig = wctdm_hooksig;
wc->span.open = wctdm_open;
wc->span.close = wctdm_close;
@@ -2966,7 +2990,7 @@ static int wctdm_hardware_init(struct wctdm *wc)
newjiffies = jiffies + HZ/10;
while(((reg = wctdm_getctl(wc,0x0000)) & 0x00000001) && (newjiffies > jiffies));
- printk("WCTDM2400P: New Reg: %08x!\n", reg);
+ printk("%s: New Reg: %08x!\n", wc->variety, reg);
/* Configure watchdogs, access, etc */
@@ -2997,7 +3021,7 @@ static int wctdm_hardware_init(struct wctdm *wc)
printk("(post) Reg fc is %08x\n", reg);
printk("Detected REG2: %08x\n", wctdm_getsdi(wc, 0x02));
#endif
- printk("wctdm2400p: reg is %08x\n", wctdm_getctl(wc, 0x0088));
+ printk("%s: reg is %08x\n", wc->variety, wctdm_getctl(wc, 0x0088));
return 0;
}
@@ -3229,13 +3253,20 @@ static void wctdm_locate_modules(struct wctdm *wc)
for (x=0;x<wc->cards;x++)
wc->modtype[x] = MOD_TYPE_FXS;
spin_unlock_irqrestore(&wc->reglock, flags);
+
#if 0
/* XXX */
cmddesc = 0;
#endif
+ /* Now that all the cards have been reset, we can stop checking them all if there aren't as many */
+ spin_lock_irqsave(&wc->reglock, flags);
+ wc->cards = wc->type;
+ spin_unlock_irqrestore(&wc->reglock, flags);
+
/* Reset modules */
for (x=0;x<wc->cards;x++) {
int sane=0,ret=0,readi=0;
+retry:
/* Init with Auto Calibration */
if (!(ret = wctdm_init_proslic(wc, x, 0, 0, sane))) {
wc->cardflag |= (1 << x);
@@ -3267,9 +3298,23 @@ static void wctdm_locate_modules(struct wctdm *wc)
wc->cardflag |= 1 << x;
printk("Port %d: Installed -- QRV DRI card\n",x + 1);
} else {
- printk("Port %d: Not installed\n", x + 1);
- wc->modtype[x] = MOD_TYPE_NONE;
- wc->cardflag |= (1 << x);
+ if ((wc->type == 8) && ((x & 0x3) == 1) && !wc->altcs[x]) {
+ spin_lock_irqsave(&wc->reglock, flags);
+ wc->modtype[x] = MOD_TYPE_FXSINIT;
+ wc->altcs[x] = 2;
+ spin_unlock_irqrestore(&wc->reglock, flags);
+ schluffen(&wc->regq);
+ spin_lock_irqsave(&wc->reglock, flags);
+ wc->modtype[x] = MOD_TYPE_FXS;
+ spin_unlock_irqrestore(&wc->reglock, flags);
+ if (debug)
+ printk("Trying port %d with alternate chip select\n", x + 1);
+ goto retry;
+ } else {
+ printk("Port %d: Not installed\n", x + 1);
+ wc->modtype[x] = MOD_TYPE_NONE;
+ wc->cardflag |= (1 << x);
+ }
}
}
}
@@ -3290,6 +3335,8 @@ static int __devinit wctdm_init_one(struct pci_dev *pdev, const struct pci_devic
int x;
int y;
static int initd_ifaces=0;
+
+ d = &wctdm800;
if(initd_ifaces){
memset((void *)ifaces,0,(sizeof(struct wctdm *))*WC_MAX_IFACES);
@@ -3313,6 +3360,7 @@ static int __devinit wctdm_init_one(struct pci_dev *pdev, const struct pci_devic
wc->curcard = -1;
wc->cards = NUM_CARDS;
wc->iobase = pci_resource_start(pdev, 0);
+ wc->type = d->ports;
wc->dev = pdev;
wc->pos = x;
wc->variety = d->name;
@@ -3321,7 +3369,7 @@ static int __devinit wctdm_init_one(struct pci_dev *pdev, const struct pci_devic
wc->dacssrc[y] = -1;
}
/* Keep track of whether we need to free the region */
- if (request_region(wc->iobase, 0xff, "wctdm"))
+ if (request_region(wc->iobase, 0xff, wc->variety))
wc->freeregion = 1;
/* Allocate enough memory for two zt chunks, receive and transmit. Each sample uses
@@ -3347,7 +3395,7 @@ static int __devinit wctdm_init_one(struct pci_dev *pdev, const struct pci_devic
init_waitqueue_head(&wc->regq);
if (wctdm_initialize(wc)) {
- printk("wctdm: Unable to intialize FXS\n");
+ printk("%s: Unable to register span with zaptel\n", wc->variety);
/* Set Reset Low */
wctdm_stop_dma(wc);
/* Free Resources */
@@ -3365,8 +3413,8 @@ static int __devinit wctdm_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, wctdm_interrupt, SA_SHIRQ, "wctdm24xxp", wc)) {
- printk("wctdm: Unable to request IRQ %d\n", pdev->irq);
+ if (request_irq(pdev->irq, wctdm_interrupt, SA_SHIRQ, wc->variety, wc)) {
+ printk("%s: Unable to request IRQ %d\n", wc->variety, pdev->irq);
if (wc->freeregion)
release_region(wc->iobase, 0xff);
pci_free_consistent(pdev, PCI_WINDOW_SIZE, (void *)wc->writechunk, wc->writedma);
@@ -3404,7 +3452,7 @@ static int __devinit wctdm_init_one(struct pci_dev *pdev, const struct pci_devic
/* Final initialization */
wctdm_post_initialize(wc);
- printk("Found a Wildcard TDM: %s (%d modules)\n", wc->variety, wc->cards);
+ printk("Found a Wildcard TDM: %s (%d modules)\n", wc->variety, wc->type);
res = 0;
} else
res = -ENOMEM;
@@ -3445,14 +3493,15 @@ static void __devexit wctdm_remove_one(struct pci_dev *pdev)
}
static struct pci_device_id wctdm_pci_tbl[] = {
- { 0xd161, 0x2400, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (unsigned long) &wctdm },
+ { 0xd161, 0x2400, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (unsigned long) &wctdm2400 },
+ { 0xd161, 0x0800, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (unsigned long) &wctdm800 },
{ 0 }
};
MODULE_DEVICE_TABLE(pci, wctdm_pci_tbl);
static struct pci_driver wctdm_driver = {
- name: "wctdm24xxp",
+ name: "wctdmxxp",
probe: wctdm_init_one,
#ifdef LINUX26
remove: __devexit_p(wctdm_remove_one),
@@ -3541,7 +3590,7 @@ MODULE_PARM(vpmdtmfsupport, "i");
MODULE_PARM(dtmfthreshold, "i");
#endif
#endif
-MODULE_DESCRIPTION("Wildcard TDM2400P Zaptel Driver");
+MODULE_DESCRIPTION("Wildcard TDMXX00P Zaptel Driver");
MODULE_AUTHOR("Mark Spencer <markster@digium.com>");
#ifdef MODULE_LICENSE
MODULE_LICENSE("GPL");