diff options
author | mattf <mattf@5390a7c7-147a-4af0-8ec9-7488f05a26cb> | 2007-01-25 22:17:16 +0000 |
---|---|---|
committer | mattf <mattf@5390a7c7-147a-4af0-8ec9-7488f05a26cb> | 2007-01-25 22:17:16 +0000 |
commit | f62ab473d3692e18d3c189908cd3c85a2ed44c08 (patch) | |
tree | 657fb6891973edf085afef12cddbef1c77222ab9 /wctdm24xxp.c | |
parent | 4064ee33062608cb774beae383e27761705e5122 (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.c | 145 |
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"); |