Search
j0ke.net Open Build Service
>
Projects
>
server:telephony
>
zaptel
> zaptel-wctel2xp.diff
Sign Up
|
Log In
Username
Password
Cancel
Overview
Repositories
Revisions
Requests
Users
Advanced
Attributes
Meta
File zaptel-wctel2xp.diff of Package zaptel (Revision 7)
Currently displaying revision
7
,
show latest
diff -uNr zaptel-1.4.8/wcte12xp/base.c zaptel-1.4/wcte12xp/base.c --- zaptel-1.4.8/wcte12xp/base.c 2008-01-11 23:39:16.000000000 +0100 +++ zaptel-1.4/wcte12xp/base.c 2008-02-03 17:46:02.000000000 +0100 @@ -47,8 +47,11 @@ #include "../wct4xxp/wct4xxp.h" /* For certain definitions */ #include "wcte12xp.h" + +#if defined(VPM_SUPPORT) #include "vpmadt032.h" #include "GpakApi.h" +#endif struct pci_driver te12xp_driver; @@ -92,6 +95,9 @@ int vpmsupport = 1; int vpmdtmfsupport = 0; int vpmtsisupport = 0; +int vpmnlptype = 1; +int vpmnlpthresh = 24; +int vpmnlpmaxsupp = 0; #endif struct t1 *ifaces[WC_MAX_IFACES]; @@ -1352,8 +1358,12 @@ snprintf(wc->span.desc, sizeof(wc->span.desc) - 1, "%s Card %d", wc->variety, wc->num); wc->span.manufacturer = "Digium"; strncpy(wc->span.devicetype, wc->variety, sizeof(wc->span.devicetype) - 1); + +#if defined(VPM_SUPPORT) if (wc->vpm150m) strncat(wc->span.devicetype, " with VPMADT032", sizeof(wc->span.devicetype) - 1); +#endif + snprintf(wc->span.location, sizeof(wc->span.location) - 1, "PCI Bus %02d Slot %02d", wc->dev->bus->number, PCI_SLOT(wc->dev->devfn) + 1); @@ -2012,9 +2022,9 @@ static void __devexit te12xp_remove_one(struct pci_dev *pdev) { - unsigned long flags; struct t1 *wc = pci_get_drvdata(pdev); #ifdef VPM_SUPPORT + unsigned long flags; struct vpm150m *vpm150m = wc->vpm150m; #endif if (!wc) @@ -2115,6 +2125,9 @@ MODULE_PARM(vpmsupport, "i"); MODULE_PARM(vpmdtmfsupport, "i"); MODULE_PARM(vpmtsisupport, "i"); +MODULE_PARM(vpmnlptype, "i"); +MODULE_PARM(vpmnlpthresh, "i"); +MODULE_PARM(vpmnlpmaxsupp, "i"); #endif #endif diff -uNr zaptel-1.4.8/wcte12xp/Kbuild zaptel-1.4/wcte12xp/Kbuild --- zaptel-1.4.8/wcte12xp/Kbuild 2007-12-11 09:43:22.000000000 +0100 +++ zaptel-1.4/wcte12xp/Kbuild 2008-02-03 17:46:02.000000000 +0100 @@ -2,6 +2,10 @@ EXTRA_CFLAGS := -I$(src)/.. -Wno-undef +ifeq ($(HOTPLUG_FIRMWARE),yes) + EXTRA_CFLAGS+=-DHOTPLUG_FIRMWARE +endif + wcte12xp-objs := base.o vpmadt032.o GpakApi.o ifneq ($(HOTPLUG_FIRMWARE),yes) diff -uNr zaptel-1.4.8/wcte12xp/Makefile zaptel-1.4/wcte12xp/Makefile --- zaptel-1.4.8/wcte12xp/Makefile 2007-12-11 09:43:22.000000000 +0100 +++ zaptel-1.4/wcte12xp/Makefile 2008-02-03 17:46:02.000000000 +0100 @@ -1,24 +1,22 @@ ifneq ($(KBUILD_EXTMOD),) -# We only get here on kernels 2.6.0-2.6.8 . +# We only get here on kernels 2.6.0-2.6.9 . # For newer kernels, Kbuild will be included directly by the kernel # build system. include $(src)/Kbuild else +# building for 2.4 kernels means no VPM support, so none of the VPM support +# modules are included in the Makefile rules + all: wcte12xp.o %.o: %.c $(CC) $(KFLAGS) -o $@ -c $< -base.o: ../zaptel.h vpmadt032.h - -vpmadt032.o: vpmadt032.h - -../firmware/zaptel-fw-vpmadt032.o: base.o - $(MAKE) -C ../firmware zaptel-fw-vpmadt032.o +base.o: ../zaptel.h -wcte12xp.o: base.o vpmadt032.o GpakApi.o ../firmware/zaptel-fw-vpmadt032.o +wcte12xp.o: base.o $(LD) -r -o $@ $^ clean: diff -uNr zaptel-1.4.8/wcte12xp/.svn/all-wcprops zaptel-1.4/wcte12xp/.svn/all-wcprops --- zaptel-1.4.8/wcte12xp/.svn/all-wcprops 1970-01-01 01:00:00.000000000 +0100 +++ zaptel-1.4/wcte12xp/.svn/all-wcprops 2008-02-03 17:46:02.000000000 +0100 @@ -0,0 +1,71 @@ +K 25 +svn:wc:ra_dav:version-url +V 47 +/svn/zaptel/!svn/ver/3748/branches/1.4/wcte12xp +END +vpmadt032.c +K 25 +svn:wc:ra_dav:version-url +V 59 +/svn/zaptel/!svn/ver/3731/branches/1.4/wcte12xp/vpmadt032.c +END +GpakApi.h +K 25 +svn:wc:ra_dav:version-url +V 57 +/svn/zaptel/!svn/ver/3371/branches/1.4/wcte12xp/GpakApi.h +END +wcte12xp.h +K 25 +svn:wc:ra_dav:version-url +V 58 +/svn/zaptel/!svn/ver/3738/branches/1.4/wcte12xp/wcte12xp.h +END +GpakErrs.h +K 25 +svn:wc:ra_dav:version-url +V 58 +/svn/zaptel/!svn/ver/3371/branches/1.4/wcte12xp/GpakErrs.h +END +vpmadt032.h +K 25 +svn:wc:ra_dav:version-url +V 59 +/svn/zaptel/!svn/ver/3649/branches/1.4/wcte12xp/vpmadt032.h +END +GpakHpi.h +K 25 +svn:wc:ra_dav:version-url +V 57 +/svn/zaptel/!svn/ver/3371/branches/1.4/wcte12xp/GpakHpi.h +END +Kbuild +K 25 +svn:wc:ra_dav:version-url +V 54 +/svn/zaptel/!svn/ver/3721/branches/1.4/wcte12xp/Kbuild +END +base.c +K 25 +svn:wc:ra_dav:version-url +V 54 +/svn/zaptel/!svn/ver/3738/branches/1.4/wcte12xp/base.c +END +GpakApi.c +K 25 +svn:wc:ra_dav:version-url +V 57 +/svn/zaptel/!svn/ver/3371/branches/1.4/wcte12xp/GpakApi.c +END +Makefile +K 25 +svn:wc:ra_dav:version-url +V 56 +/svn/zaptel/!svn/ver/3748/branches/1.4/wcte12xp/Makefile +END +gpakenum.h +K 25 +svn:wc:ra_dav:version-url +V 58 +/svn/zaptel/!svn/ver/3371/branches/1.4/wcte12xp/gpakenum.h +END diff -uNr zaptel-1.4.8/wcte12xp/.svn/dir-prop-base zaptel-1.4/wcte12xp/.svn/dir-prop-base --- zaptel-1.4.8/wcte12xp/.svn/dir-prop-base 1970-01-01 01:00:00.000000000 +0100 +++ zaptel-1.4/wcte12xp/.svn/dir-prop-base 2008-02-03 17:46:02.000000000 +0100 @@ -0,0 +1,8 @@ +K 10 +svn:ignore +V 19 +*.mod.c +*.cmd +*.ko + +END diff -uNr zaptel-1.4.8/wcte12xp/.svn/entries zaptel-1.4/wcte12xp/.svn/entries --- zaptel-1.4.8/wcte12xp/.svn/entries 1970-01-01 01:00:00.000000000 +0100 +++ zaptel-1.4/wcte12xp/.svn/entries 2008-02-03 17:46:02.000000000 +0100 @@ -0,0 +1,160 @@ +8 + +dir +3788 +http://svn.digium.com/svn/zaptel/branches/1.4/wcte12xp +http://svn.digium.com/svn/zaptel + + + +2008-01-27T23:10:09.554228Z +3748 +tzafrir +has-props + +svn:special svn:externals svn:needs-lock + + + + + + + + + + + +f558416c-6c06-0410-9f27-dde2687782d0 + +vpmadt032.c +file + + + + +2008-02-03T16:46:02.000000Z +7a7bc225dfd5968b76b382d2b79a6a09 +2008-01-23T21:35:23.884040Z +3731 +mattf + +GpakApi.h +file + + + + +2008-02-03T16:46:02.000000Z +458122bf91992498df9699f16feda1bf +2007-12-08T19:55:17.407807Z +3371 +mattf + +wcte12xp.h +file + + + + +2008-02-03T16:46:02.000000Z +48256930bd05517fe422981f3941f1c6 +2008-01-25T23:13:41.201127Z +3738 +kpfleming + +GpakErrs.h +file + + + + +2008-02-03T16:46:02.000000Z +5e98eff72f35f0c81277b0090fb0f63f +2007-12-08T19:55:17.407807Z +3371 +mattf + +vpmadt032.h +file + + + + +2008-02-03T16:46:02.000000Z +4a0b36e3b78fe54678b22a6b5539ee86 +2008-01-10T23:15:28.791257Z +3649 +kpfleming + +GpakHpi.h +file + + + + +2008-02-03T16:46:02.000000Z +e0ff5314c3e64c96c20203e1f0666264 +2007-12-08T19:55:17.407807Z +3371 +mattf + +Kbuild +file + + + + +2008-02-03T16:46:02.000000Z +6a393d4fd432fa0752701dd71f625a1b +2008-01-21T23:15:03.509891Z +3721 +tzafrir + +base.c +file + + + + +2008-02-03T16:46:02.000000Z +da12b534379334f927f32f43e054273d +2008-01-25T23:13:41.201127Z +3738 +kpfleming + +GpakApi.c +file + + + + +2008-02-03T16:46:02.000000Z +2c8fbd44ee5c365dcc3214c1d2c1341e +2007-12-08T19:55:17.407807Z +3371 +mattf + +Makefile +file + + + + +2008-02-03T16:46:02.000000Z +156fe8f2b1e7988b311fe2e6fb4c9d2c +2008-01-27T23:10:09.554228Z +3748 +tzafrir + +gpakenum.h +file + + + + +2008-02-03T16:46:02.000000Z +391884e1113d265ad0a2d194bf722d1e +2007-12-08T19:55:17.407807Z +3371 +mattf + diff -uNr zaptel-1.4.8/wcte12xp/.svn/format zaptel-1.4/wcte12xp/.svn/format --- zaptel-1.4.8/wcte12xp/.svn/format 1970-01-01 01:00:00.000000000 +0100 +++ zaptel-1.4/wcte12xp/.svn/format 2008-02-03 17:46:02.000000000 +0100 @@ -0,0 +1 @@ +8 diff -uNr zaptel-1.4.8/wcte12xp/.svn/text-base/base.c.svn-base zaptel-1.4/wcte12xp/.svn/text-base/base.c.svn-base --- zaptel-1.4.8/wcte12xp/.svn/text-base/base.c.svn-base 1970-01-01 01:00:00.000000000 +0100 +++ zaptel-1.4/wcte12xp/.svn/text-base/base.c.svn-base 2008-02-03 17:46:02.000000000 +0100 @@ -0,0 +1,2139 @@ +/* + * Digium, Inc. Wildcard TE12xP T1/E1 card Driver + * + * Written by Michael Spiceland <mspiceland@digium.com> + * + * Adapted from the wctdm24xxp and wcte11xp drivers originally + * written by Mark Spencer <markster@digium.com> + * Matthew Fredrickson <creslin@digium.com> + * William Meadows <wmeadows@digium.com> + * + * Copyright (C) 2007, Digium, Inc. + * + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#include <linux/kernel.h> +#include <linux/errno.h> +#include <linux/module.h> +#include <linux/init.h> +#include <linux/errno.h> +#include <linux/pci.h> +#include <linux/interrupt.h> +#include <linux/proc_fs.h> +#include <linux/interrupt.h> + +#ifdef LINUX26 +#include <linux/moduleparam.h> +#endif + +#include "zaptel.h" + +#include "../wct4xxp/wct4xxp.h" /* For certain definitions */ + +#include "wcte12xp.h" + +#if defined(VPM_SUPPORT) +#include "vpmadt032.h" +#include "GpakApi.h" +#endif + +struct pci_driver te12xp_driver; + +static int chanmap_t1[] = +{ 2,1,0, + 6,5,4, + 10,9,8, + 14,13,12, + 18,17,16, + 22,21,20, + 26,25,24, + 30,29,28 }; + +static int chanmap_e1[] = +{ 2,1,0, + 7,6,5,4, + 11,10,9,8, + 15,14,13,12, + 19,18,17,16, + 23,22,21,20, + 27,26,25,24, + 31,30,29,28 }; + +static int chanmap_e1uc[] = +{ 3,2,1,0, + 7,6,5,4, + 11,10,9,8, + 15,14,13,12, + 19,18,17,16, + 23,22,21,20, + 27,26,25,24, + 31,30,29,28 }; + +int debug = 0; +static int j1mode = 0; +static int alarmdebounce = 0; +static int loopback = 0; +static int t1e1override = -1; +static int unchannelized = 0; +#ifdef VPM_SUPPORT +int vpmsupport = 1; +int vpmdtmfsupport = 0; +int vpmtsisupport = 0; +int vpmnlptype = 1; +int vpmnlpthresh = 24; +int vpmnlpmaxsupp = 0; +#endif + +struct t1 *ifaces[WC_MAX_IFACES]; +spinlock_t ifacelock = SPIN_LOCK_UNLOCKED; + +struct t1_desc { + char *name; + int flags; +}; + +static struct t1_desc te120p = { "Wildcard TE120P", 0 }; +static struct t1_desc te122 = { "Wildcard TE122", 0 }; +static struct t1_desc te121 = { "Wildcard TE121", 0 }; + +int schluffen(wait_queue_head_t *q) +{ + DECLARE_WAITQUEUE(wait, current); + add_wait_queue(q, &wait); + current->state = TASK_INTERRUPTIBLE; + if (!signal_pending(current)) schedule(); + current->state = TASK_RUNNING; + remove_wait_queue(q, &wait); + if (signal_pending(current)) return -ERESTARTSYS; + return(0); +} + +static inline int empty_slot(struct t1 *wc) +{ + unsigned int x; + + for (x = 0; x < sizeof(wc->cmdq.cmds) / sizeof(wc->cmdq.cmds[0]); x++) { + if (!wc->cmdq.cmds[x].flags && !wc->cmdq.cmds[x].address) + return x; + } + return -1; +} + +static inline void __t1_setctl(struct t1 *wc, unsigned int addr, unsigned int val) +{ + outl(val, wc->iobase + addr); +} + +static inline void t1_setctl(struct t1 *wc, unsigned int addr, unsigned int val) +{ + unsigned long flags; + + spin_lock_irqsave(&wc->reglock, flags); + __t1_setctl(wc, addr, val); + spin_unlock_irqrestore(&wc->reglock, flags); +} + +static inline unsigned int __t1_getctl(struct t1 *wc, unsigned int addr) +{ + return inl(wc->iobase + addr); +} + +static inline unsigned int t1_getctl(struct t1 *wc, unsigned int addr) +{ + unsigned long flags; + unsigned int val; + + spin_lock_irqsave(&wc->reglock, flags); + val = __t1_getctl(wc, addr); + spin_unlock_irqrestore(&wc->reglock, flags); + + return val; +} + +static void t1_init_descriptors(struct t1 *wc) +{ + volatile unsigned int *descrip; + dma_addr_t descripdma; + dma_addr_t writedma; + dma_addr_t readdma; + int x; + + descrip = wc->descripchunk; + descripdma = wc->descripdma; + writedma = wc->writedma; + readdma = wc->readdma; + + for (x = 0; x < ERING_SIZE; x++) { + if (x < ERING_SIZE - 1) + descripdma += 16; + else + descripdma = wc->descripdma; + + /* Transmit descriptor */ + descrip[0] = 0x80000000; + descrip[1] = 0xe5800000 | (SFRAME_SIZE); + if (x % 2) + descrip[2] = writedma + SFRAME_SIZE; + else + descrip[2] = writedma; + descrip[3] = descripdma; + + /* Receive descriptor */ + descrip[0 + ERING_SIZE * 4] = 0x80000000; + descrip[1 + ERING_SIZE * 4] = 0x01000000 | (SFRAME_SIZE); + if (x % 2) + descrip[2 + ERING_SIZE * 4] = readdma + SFRAME_SIZE; + else + descrip[2 + ERING_SIZE * 4] = readdma; + descrip[3 + ERING_SIZE * 4] = descripdma + ERING_SIZE * 16; + + /* Advance descriptor */ + descrip += 4; + } +} + +static inline void t1_reinit_descriptor(struct t1 *wc, int tx, int dbl, char *s) +{ + int o2 = dbl * 4; + + if (!tx) + o2 += ERING_SIZE * 4; + + wc->descripchunk[o2] = 0x80000000; +} + +static inline void cmd_dequeue(struct t1 *wc, volatile unsigned char *writechunk, int eframe, int slot) +{ + struct command *curcmd=NULL; + unsigned int x; + + /* Skip audio */ + writechunk += 66; + /* Search for something waiting to transmit */ + if ((slot < 6) && (eframe) && (eframe < ZT_CHUNKSIZE - 1)) { + /* only 6 useable cs slots per */ + + /* framer */ + for (x = 0; x < sizeof(wc->cmdq.cmds) / sizeof(wc->cmdq.cmds[0]); x++) { + if ((wc->cmdq.cmds[x].flags & (__CMD_RD | __CMD_WR | __CMD_LEDS | __CMD_PINS)) && + !(wc->cmdq.cmds[x].flags & (__CMD_TX | __CMD_FIN))) { + curcmd = &wc->cmdq.cmds[x]; + wc->cmdq.cmds[x].flags |= __CMD_TX; + wc->cmdq.cmds[x].ident = wc->txident; + break; + } + } + if (!curcmd) { + curcmd = &wc->dummy; + /* If nothing else, use filler */ + curcmd->address = 0x4a; + curcmd->data = 0x00; + curcmd->flags = __CMD_RD; + } + curcmd->cs_slot = slot; + if (curcmd->flags & __CMD_WR) + writechunk[CMD_BYTE(slot,0,0)] = 0x0c; /* 0c write command */ + else if (curcmd->flags & __CMD_LEDS) + writechunk[CMD_BYTE(slot,0,0)] = 0x10 | ((curcmd->address) & 0x0E); /* led set command */ + else if (curcmd->flags & __CMD_PINS) + writechunk[CMD_BYTE(slot,0,0)] = 0x30; /* CPLD2 pin state */ + else + writechunk[CMD_BYTE(slot,0,0)] = 0x0a; /* read command */ + writechunk[CMD_BYTE(slot,1,0)] = curcmd->address; + writechunk[CMD_BYTE(slot,2,0)] = curcmd->data; + } + +} + +static inline void cmd_decipher(struct t1 *wc, volatile unsigned char *readchunk) +{ + unsigned char ident, cs_slot; + unsigned int x; + unsigned int is_vpm = 0; + + /* Skip audio */ + readchunk += 66; + /* Search for any pending results */ + for (x = 0; x < sizeof(wc->cmdq.cmds) / sizeof(wc->cmdq.cmds[0]); x++) { + if ((wc->cmdq.cmds[x].flags & (__CMD_RD | __CMD_WR | __CMD_LEDS | __CMD_PINS)) && + (wc->cmdq.cmds[x].flags & (__CMD_TX)) && + !(wc->cmdq.cmds[x].flags & (__CMD_FIN))) { + ident = wc->cmdq.cmds[x].ident; + cs_slot = wc->cmdq.cmds[x].cs_slot; + + if (ident == wc->rxident) { + /* Store result */ + wc->cmdq.cmds[x].data |= readchunk[CMD_BYTE(cs_slot,2,is_vpm)]; + /*printk("answer in rxident=%d cs_slot=%d is %d CMD_BYTE=%d jiffies=%d\n", ident, cs_slot, last_read_command, CMD_BYTE(cs_slot, 2), jiffies); */ + wc->cmdq.cmds[x].flags |= __CMD_FIN; + if (wc->cmdq.cmds[x].flags & (__CMD_WR | __CMD_LEDS)) + /* clear out writes (and leds) since they need no ack */ + memset(&wc->cmdq.cmds[x], 0, sizeof(wc->cmdq.cmds[x])); + } + } + } +} + +static inline unsigned int __t1_sdi_clk(struct t1 *wc) +{ + unsigned int ret; + + wc->sdi &= ~SDI_CLK; + __t1_setctl(wc, 0x0048, wc->sdi); + ret = __t1_getctl(wc, 0x0048); + wc->sdi |= SDI_CLK; + __t1_setctl(wc, 0x0048, wc->sdi); + return ret & SDI_DIN; +} + +static inline void __t1_sdi_sendbits(struct t1 *wc, unsigned int bits, int count) +{ + wc->sdi &= ~SDI_DREAD; + __t1_setctl(wc, 0x0048, wc->sdi); + while (count--) { + if (bits & (1 << count)) + wc->sdi |= SDI_DOUT; + else + wc->sdi &= ~SDI_DOUT; + __t1_sdi_clk(wc); + } +} + +static inline unsigned int __t1_sdi_recvbits(struct t1 *wc, int count) +{ + unsigned int bits=0; + + wc->sdi |= SDI_DREAD; + __t1_setctl(wc, 0x0048, wc->sdi); + while (count--) { + bits <<= 1; + if (__t1_sdi_clk(wc)) + bits |= 1; + else + bits &= ~1; + } + return bits; +} + +static inline unsigned short __t1_getsdi(struct t1 *wc, unsigned char addr) +{ + unsigned int bits; + + /* Send preamble */ + bits = 0xffffffff; + __t1_sdi_sendbits(wc, bits, 32); + bits = (0x6 << 10) | (1 << 5) | (addr); + __t1_sdi_sendbits(wc, bits, 14); + + return __t1_sdi_recvbits(wc, 18); +} + +static inline unsigned short t1_getsdi(struct t1 *wc, unsigned char addr) +{ + unsigned long flags; + unsigned short val; + + spin_lock_irqsave(&wc->reglock, flags); + val = __t1_getsdi(wc, addr); + spin_unlock_irqrestore(&wc->reglock, flags); + + return val; +} + +static inline void __t1_setsdi(struct t1 *wc, unsigned char addr, unsigned short value) +{ + unsigned int bits; + + /* Send preamble */ + bits = 0xffffffff; + __t1_sdi_sendbits(wc, bits, 32); + bits = (0x5 << 12) | (1 << 7) | (addr << 2) | 0x2; + __t1_sdi_sendbits(wc, bits, 16); + __t1_sdi_sendbits(wc, value, 16); +} + +static inline void t1_setsdi(struct t1 *wc, unsigned char addr, unsigned short value) +{ + unsigned long flags; + + spin_lock_irqsave(&wc->reglock, flags); + __t1_setsdi(wc, addr, value); + spin_unlock_irqrestore(&wc->reglock, flags); +} + +static inline int t1_setreg_full(struct t1 *wc, int addr, int val, int inisr, int vpm_num) +{ + unsigned long flags; + int hit; + int ret; + + + do { + if (!inisr) + spin_lock_irqsave(&wc->reglock, flags); + hit = empty_slot(wc); + if (hit > -1) { + wc->cmdq.cmds[hit].address = addr; + wc->cmdq.cmds[hit].data = val; + wc->cmdq.cmds[hit].flags |= __CMD_WR; + if(vpm_num >= 0) { + wc->cmdq.cmds[hit].flags |= __CMD_VPM; + wc->cmdq.cmds[hit].vpm_num = vpm_num; + } + } + if (inisr) + break; + + spin_unlock_irqrestore(&wc->reglock, flags); + if (hit < 0) { + if ((ret = schluffen(&wc->regq))) + return ret; + } + } while (hit < 0); + + return (hit > -1) ? 0 : -1; +} + +static inline int t1_setreg(struct t1 *wc, int addr, int val) +{ + return t1_setreg_full(wc, addr, val, 0, NOT_VPM); +} + +/*************************************************************************** + * clean_leftovers() + * + * Check for unconsumed isr register reads and clean them up. + **************************************************************************/ +static inline void clean_leftovers(struct t1 *wc) +{ + unsigned int x; + int count = 0; + + /* find our requested command */ + for (x = 0; x < sizeof(wc->cmdq.cmds) / sizeof(wc->cmdq.cmds[0]); x++) { + if ((wc->cmdq.cmds[x].flags & __CMD_RD) && + (wc->cmdq.cmds[x].flags & __CMD_ISR) && + !(wc->cmdq.cmds[x].flags & __CMD_FIN)) { + debug_printk(1,"leftover isr read! %d", count); + memset(&wc->cmdq.cmds[x], 0, sizeof(wc->cmdq.cmds[x])); + } + } +} + +/******************************************************************** + * t1_getreg_isr() + * + * Called in interrupt context to retrieve a value already requested + * by the normal t1_getreg(). + *******************************************************************/ +static inline int t1_getreg_isr(struct t1 *wc, int addr) +{ + int hit=-1; + int ret; + unsigned int x; + + /* find our requested command */ + for (x = 0;x < sizeof(wc->cmdq.cmds) / sizeof(wc->cmdq.cmds[0]); x++) { + if ((wc->cmdq.cmds[x].flags & __CMD_RD) && + (wc->cmdq.cmds[x].flags & __CMD_FIN) && + (wc->cmdq.cmds[x].address==addr)) { + hit = x; + break; + } + } + + if (hit < 0) { + debug_printk(2, "t1_getreg_isr() no addr=%02x\n", addr); + return -1; /* oops, couldn't find it */ + } + + ret = wc->cmdq.cmds[hit].data; + memset(&wc->cmdq.cmds[hit], 0, sizeof(struct command)); + + return ret; +} + +static inline int t1_getreg_full(struct t1 *wc, int addr, int inisr, int vpm_num) +{ + unsigned long flags; + int hit; + int ret = 0; + + do { + if (!inisr) { + spin_lock_irqsave(&wc->reglock, flags); + } + hit = empty_slot(wc); + if (hit > -1) { + wc->cmdq.cmds[hit].address = addr; + wc->cmdq.cmds[hit].data = 0x00; + wc->cmdq.cmds[hit].flags |= __CMD_RD; + if(vpm_num >= 0) { + wc->cmdq.cmds[hit].flags |= __CMD_VPM; + wc->cmdq.cmds[hit].vpm_num = vpm_num; + } + if (inisr) + wc->cmdq.cmds[hit].flags |= __CMD_ISR; + } + if (inisr) /* must be requested in t1_getreg_isr() */ + return (hit > -1) ? 0 : -1; + else { + spin_unlock_irqrestore(&wc->reglock, flags); + } + if (hit < 0) { + if ((ret = schluffen(&wc->regq))) + return ret; + } + } while (hit < 0); + + do { + spin_lock_irqsave(&wc->reglock, flags); + if (wc->cmdq.cmds[hit].flags & __CMD_FIN) { + ret = wc->cmdq.cmds[hit].data; + memset(&wc->cmdq.cmds[hit], 0, sizeof(wc->cmdq.cmds[hit])); + hit = -1; + } + spin_unlock_irqrestore(&wc->reglock, flags); + if (hit > -1) { + if ((ret = schluffen(&wc->regq))) + return ret; + } + } while (hit > -1); + + return ret; +} + +static inline int t1_getreg(struct t1 *wc, int addr, int inisr) +{ + return t1_getreg_full(wc, addr, inisr, NOT_VPM); +} + +static inline int t1_setleds(struct t1 *wc, int leds, int inisr) +{ + unsigned long flags; + int hit; + int ret = 0; + + leds = ~leds & 0x0E; /* invert the LED bits (3 downto 1)*/ + + do { + if (!inisr) { + spin_lock_irqsave(&wc->reglock, flags); + } + hit = empty_slot(wc); + if (hit > -1) { + wc->cmdq.cmds[hit].flags |= __CMD_LEDS; + wc->cmdq.cmds[hit].address = leds; + } + if (inisr) { + break; + } else { + spin_unlock_irqrestore(&wc->reglock, flags); + } + if (hit < 0) { + if ((ret = schluffen(&wc->regq))) + return ret; + } + } while (hit < 0); + + return (hit > -1) ? 0 : -1; +} + +static inline int t1_getpins(struct t1 *wc, int inisr) +{ + unsigned long flags; + int hit; + int ret = 0; + + do { + spin_lock_irqsave(&wc->reglock, flags); + hit = empty_slot(wc); + if (hit > -1) { + wc->cmdq.cmds[hit].address = 0x00; + wc->cmdq.cmds[hit].data = 0x00; + wc->cmdq.cmds[hit].flags |= __CMD_PINS; + } + spin_unlock_irqrestore(&wc->reglock, flags); + if (inisr) + return (hit > -1) ? 0 : -1; + if (hit < 0) { + if ((ret = schluffen(&wc->regq))) + return ret; + } + } while (hit < 0); + + do { + spin_lock_irqsave(&wc->reglock, flags); + if (wc->cmdq.cmds[hit].flags & __CMD_FIN) { + ret = wc->cmdq.cmds[hit].data; + memset(&wc->cmdq.cmds[hit], 0, sizeof(wc->cmdq.cmds[hit])); + hit = -1; + } + spin_unlock_irqrestore(&wc->reglock, flags); + if (hit > -1) { + if ((ret = schluffen(&wc->regq))) + return ret; + } + } while (hit > -1); + + return ret; +} + +static void t1_setintmask(struct t1 *wc, unsigned int intmask) +{ + wc->intmask = intmask; + t1_setctl(wc, 0x0038, intmask); +} + +static void t1_enable_interrupts(struct t1 *wc) +{ + /* Enable interrupts */ + t1_setintmask(wc, 0x00010041); /* only RX */ +} + +static void t1_disable_interrupts(struct t1 *wc) +{ + /* Disable interrupts */ + t1_setintmask(wc, 0x00000000); + t1_setctl(wc, 0x0084, 0x00000000); +} + +static void t1_start_dma(struct t1 *wc) +{ + unsigned int reg; + int x; + + wmb(); + t1_setctl(wc, 0x0020, wc->descripdma); + t1_setctl(wc, 0x0018, wc->descripdma + (16 * ERING_SIZE)); + /* Start receiver/transmitter */ + reg = t1_getctl(wc, 0x0030); + t1_setctl(wc, 0x0030, reg | 0x00002002); + t1_setctl(wc, 0x0008, 0x00000000); + t1_setctl(wc, 0x0010, 0x00000000); + reg = t1_getctl(wc, 0x0028); + t1_setctl(wc, 0x0028, reg); + + /* Set Reset - now with MAGIC TIPS */ + t1_setctl(wc, 0x0048, 0x00000000); + for (x = 0; x < 10; x++) + schluffen(&wc->regq); + /* Clear reset */ + t1_setctl(wc, 0x0048, 0x00010000); + for (x = 0; x < 10; x++) + schluffen(&wc->regq); + /* Switch to caring only about receive interrupts */ + t1_setintmask(wc, 0x00010040); +} + +static void t1_stop_dma(struct t1 *wc) +{ + /* Disable interrupts and reset */ + unsigned int reg; + + /* Disable interrupts */ + t1_setintmask(wc, 0x00000000); + t1_setctl(wc, 0x0084, 0x00000000); + t1_setctl(wc, 0x0048, 0x00000000); + /* Reset the part to be on the safe side */ + reg = t1_getctl(wc, 0x0000); + reg |= 0x00000001; + t1_setctl(wc, 0x0000, reg); +} + +static void __t1xxp_set_clear(struct t1 *wc, int channo) +{ + int i,j; + int ret; + unsigned short val=0; + + for (i = 0; i < 24; i++) { + j = (i / 8); + if (wc->span.chans[i].flags & ZT_FLAG_CLEAR) + val |= 1 << (7 - (i % 8)); + if (((i % 8)==7) && /* write byte every 8 channels */ + ((channo < 0) || /* channo=-1 means all channels */ + (j == (channo-1)/8) )) { /* only the register for this channo */ + ret = t1_setreg_full(wc, 0x2f + j, val, 1, NOT_VPM); + if (ret < 0) + module_printk("set_clear failed for chan %d!\n",i); + val = 0; + } + } +} + +static void t1_release(struct t1 *wc) +{ + zt_unregister(&wc->span); + if (wc->freeregion) + release_region(wc->iobase, 0xff); + kfree(wc); + printk("Freed a Wildcard TE12xP\n"); +} + +static void t4_serial_setup(struct t1 *wc) +{ + module_printk("Setting up global serial parameters for %s\n", + wc->spantype == TYPE_E1 ? (unchannelized ? "Unchannelized E1" : "E1") : "T1"); + + t1_setreg(wc, 0x85, 0xe0); /* GPC1: Multiplex mode enabled, FSC is output, active low, RCLK from channel 0 */ + t1_setreg(wc, 0x08, 0x05); /* IPC: Interrupt push/pull active low */ + + /* Global clocks (8.192 Mhz CLK) */ + t1_setreg(wc, 0x92, 0x00); + t1_setreg(wc, 0x93, 0x18); + t1_setreg(wc, 0x94, 0xfb); + t1_setreg(wc, 0x95, 0x0b); + t1_setreg(wc, 0x96, 0x00); + t1_setreg(wc, 0x97, 0x0b); + t1_setreg(wc, 0x98, 0xdb); + t1_setreg(wc, 0x99, 0xdf); + + /* Configure interrupts */ + t1_setreg(wc, 0x46, 0xc0); /* GCR: Interrupt on Activation/Deactivation of AIX, LOS */ + + /* Configure system interface */ + t1_setreg(wc, 0x3e, 0x0a /* 0x02 */); /* SIC1: 4.096 Mhz clock/bus, double buffer receive / transmit, byte interleaved */ + t1_setreg(wc, 0x3f, 0x00); /* SIC2: No FFS, no center receive eliastic buffer, phase 0 */ + t1_setreg(wc, 0x40, 0x04); /* SIC3: Edges for capture */ + t1_setreg(wc, 0x44, 0x30); /* CMR1: RCLK is at 8.192 Mhz dejittered */ + t1_setreg(wc, 0x45, 0x00); /* CMR2: We provide sync and clock for tx and rx. */ + t1_setreg(wc, 0x22, 0x00); /* XC0: Normal operation of Sa-bits */ + t1_setreg(wc, 0x23, 0x04); /* XC1: 0 offset */ + t1_setreg(wc, 0x24, 0x00); /* RC0: Just shy of 255 */ + t1_setreg(wc, 0x25, 0x05); /* RC1: The rest of RC0 */ + + /* Configure ports */ + t1_setreg(wc, 0x80, 0x00); /* PC1: SPYR/SPYX input on RPA/XPA */ + t1_setreg(wc, 0x81, 0x22); /* PC2: RMFB/XSIG output/input on RPB/XPB */ + t1_setreg(wc, 0x82, 0x65); /* PC3: Some unused stuff */ + t1_setreg(wc, 0x83, 0x35); /* PC4: Some more unused stuff */ + t1_setreg(wc, 0x84, 0x31); /* PC5: XMFS active low, SCLKR is input, RCLK is output */ + t1_setreg(wc, 0x86, 0x03); /* PC6: CLK1 is Tx Clock output, CLK2 is 8.192 Mhz from DCO-R */ + t1_setreg(wc, 0x3b, 0x00); /* Clear LCR1 */ +} + +static void t1_configure_t1(struct t1 *wc, int lineconfig, int txlevel) +{ + unsigned int fmr4, fmr2, fmr1, fmr0, lim2; + char *framing, *line; + int mytxlevel; + + if ((txlevel > 7) || (txlevel < 4)) + mytxlevel = 0; + else + mytxlevel = txlevel - 4; + fmr1 = 0x9e; /* FMR1: Mode 0, T1 mode, CRC on for ESF, 2.048 Mhz system data rate, no XAIS */ + fmr2 = 0x22; /* FMR2: no payload loopback, auto send yellow alarm */ + if (loopback) + fmr2 |= 0x4; + + if (j1mode) + fmr4 = 0x1c; + else + fmr4 = 0x0c; /* FMR4: Lose sync on 2 out of 5 framing bits, auto resync */ + + lim2 = 0x21; /* LIM2: 50% peak is a "1", Advanced Loss recovery */ + lim2 |= (mytxlevel << 6); /* LIM2: Add line buildout */ + t1_setreg(wc, 0x1d, fmr1); + t1_setreg(wc, 0x1e, fmr2); + + /* Configure line interface */ + if (lineconfig & ZT_CONFIG_AMI) { + line = "AMI"; + fmr0 = 0xa0; + } else { + line = "B8ZS"; + fmr0 = 0xf0; + } + if (lineconfig & ZT_CONFIG_D4) { + framing = "D4"; + } else { + framing = "ESF"; + fmr4 |= 0x2; + fmr2 |= 0xc0; + } + t1_setreg(wc, 0x1c, fmr0); + + t1_setreg(wc, 0x20, fmr4); + t1_setreg(wc, 0x21, 0x40); /* FMR5: Enable RBS mode */ + + t1_setreg(wc, 0x37, 0xf8); /* LIM1: Clear data in case of LOS, Set receiver threshold (0.5V), No remote loop, no DRS */ + t1_setreg(wc, 0x36, 0x08); /* LIM0: Enable auto long haul mode, no local loop (must be after LIM1) */ + + t1_setreg(wc, 0x02, 0x50); /* CMDR: Reset the receiver and transmitter line interface */ + t1_setreg(wc, 0x02, 0x00); /* CMDR: Reset the receiver and transmitter line interface */ + + t1_setreg(wc, 0x3a, lim2); /* LIM2: 50% peak amplitude is a "1" */ + t1_setreg(wc, 0x38, 0x0a); /* PCD: LOS after 176 consecutive "zeros" */ + t1_setreg(wc, 0x39, 0x15); /* PCR: 22 "ones" clear LOS */ + + if (j1mode) + t1_setreg(wc, 0x24, 0x80); /* J1 overide */ + + /* Generate pulse mask for T1 */ + switch (mytxlevel) { + case 3: + t1_setreg(wc, 0x26, 0x07); /* XPM0 */ + t1_setreg(wc, 0x27, 0x01); /* XPM1 */ + t1_setreg(wc, 0x28, 0x00); /* XPM2 */ + break; + case 2: + t1_setreg(wc, 0x26, 0x8c); /* XPM0 */ + t1_setreg(wc, 0x27, 0x11); /* XPM1 */ + t1_setreg(wc, 0x28, 0x01); /* XPM2 */ + break; + case 1: + t1_setreg(wc, 0x26, 0x8c); /* XPM0 */ + t1_setreg(wc, 0x27, 0x01); /* XPM1 */ + t1_setreg(wc, 0x28, 0x00); /* XPM2 */ + break; + case 0: + default: + t1_setreg(wc, 0x26, 0xd7); /* XPM0 */ + t1_setreg(wc, 0x27, 0x22); /* XPM1 */ + t1_setreg(wc, 0x28, 0x01); /* XPM2 */ + break; + } + + module_printk("Span configured for %s/%s\n", framing, line); +} + +static void t1_configure_e1(struct t1 *wc, int lineconfig) +{ + unsigned int fmr2, fmr1, fmr0; + unsigned int cas = 0; + char *crc4 = ""; + char *framing, *line; + + fmr1 = 0x46; /* FMR1: E1 mode, Automatic force resync, PCM30 mode, 8.192 Mhz backplane, no XAIS */ + fmr2 = 0x03; /* FMR2: Auto transmit remote alarm, auto loss of multiframe recovery, no payload loopback */ + if (unchannelized) + fmr2 |= 0x30; + if (loopback) + fmr2 |= 0x4; + if (lineconfig & ZT_CONFIG_CRC4) { + fmr1 |= 0x08; /* CRC4 transmit */ + fmr2 |= 0xc0; /* CRC4 receive */ + crc4 = "/CRC4"; + } + t1_setreg(wc, 0x1d, fmr1); + t1_setreg(wc, 0x1e, fmr2); + + /* Configure line interface */ + if (lineconfig & ZT_CONFIG_AMI) { + line = "AMI"; + fmr0 = 0xa0; + } else { + line = "HDB3"; + fmr0 = 0xf0; + } + if (lineconfig & ZT_CONFIG_CCS) { + framing = "CCS"; + } else { + framing = "CAS"; + cas = 0x40; + } + t1_setreg(wc, 0x1c, fmr0); + + if (unchannelized) + t1_setreg(wc, 0x1f, 0x40); + + t1_setreg(wc, 0x37, 0xf0 /*| 0x6 */ ); /* LIM1: Clear data in case of LOS, Set receiver threshold (0.5V), No remote loop, no DRS */ + t1_setreg(wc, 0x36, 0x08); /* LIM0: Enable auto long haul mode, no local loop (must be after LIM1) */ + + t1_setreg(wc, 0x02, 0x50); /* CMDR: Reset the receiver and transmitter line interface */ + t1_setreg(wc, 0x02, 0x00); /* CMDR: Reset the receiver and transmitter line interface */ + + /* Condition receive line interface for E1 after reset */ + t1_setreg(wc, 0xbb, 0x17); + t1_setreg(wc, 0xbc, 0x55); + t1_setreg(wc, 0xbb, 0x97); + t1_setreg(wc, 0xbb, 0x11); + t1_setreg(wc, 0xbc, 0xaa); + t1_setreg(wc, 0xbb, 0x91); + t1_setreg(wc, 0xbb, 0x12); + t1_setreg(wc, 0xbc, 0x55); + t1_setreg(wc, 0xbb, 0x92); + t1_setreg(wc, 0xbb, 0x0c); + t1_setreg(wc, 0xbb, 0x00); + t1_setreg(wc, 0xbb, 0x8c); + + t1_setreg(wc, 0x3a, 0x20); /* LIM2: 50% peak amplitude is a "1" */ + t1_setreg(wc, 0x38, 0x0a); /* PCD: LOS after 176 consecutive "zeros" */ + t1_setreg(wc, 0x39, 0x15); /* PCR: 22 "ones" clear LOS */ + + t1_setreg(wc, 0x20, 0x9f); /* XSW: Spare bits all to 1 */ + if (unchannelized) + t1_setreg(wc, 0x21, 0x3c); + else + t1_setreg(wc, 0x21, 0x1c|cas); /* XSP: E-bit set when async. AXS auto, XSIF to 1 */ + + + /* Generate pulse mask for E1 */ + t1_setreg(wc, 0x26, 0x54); /* XPM0 */ + t1_setreg(wc, 0x27, 0x02); /* XPM1 */ + t1_setreg(wc, 0x28, 0x00); /* XPM2 */ + module_printk("Span configured for %s/%s%s\n", framing, line, crc4); +} + +static void t1xxp_framer_start(struct t1 *wc, struct zt_span *span) +{ + int alreadyrunning = wc->span.flags & ZT_FLAG_RUNNING; + unsigned long flags; + + if (wc->spantype == TYPE_E1) { /* if this is an E1 card */ + t1_configure_e1(wc, span->lineconfig); + } else { /* is a T1 card */ + t1_configure_t1(wc, span->lineconfig, span->txlevel); + __t1xxp_set_clear(wc, -1); + } + + spin_lock_irqsave(&wc->reglock, flags); + if (!alreadyrunning) + wc->span.flags |= ZT_FLAG_RUNNING; + spin_unlock_irqrestore(&wc->reglock, flags); +} + +static int t1xxp_startup(struct zt_span *span) +{ + struct t1 *wc = span->pvt; + int i; + + /* initialize the start value for the entire chunk of last ec buffer */ + for (i = 0; i < span->channels; i++) { + memset(wc->ec_chunk1[i], ZT_LIN2X(0, &span->chans[i]), ZT_CHUNKSIZE); + memset(wc->ec_chunk2[i], ZT_LIN2X(0, &span->chans[i]), ZT_CHUNKSIZE); + } + + /* Reset framer with proper parameters and start */ + t1xxp_framer_start(wc, span); + debug_printk(1, "Calling startup (flags is %d)\n", span->flags); + + return 0; +} + +static int t1xxp_shutdown(struct zt_span *span) +{ + struct t1 *wc = span->pvt; + unsigned long flags; + + t1_setreg(wc, 0x46, 0x41); /* GCR: Interrupt on Activation/Deactivation of AIX, LOS */ + spin_lock_irqsave(&wc->reglock, flags); + span->flags &= ~ZT_FLAG_RUNNING; + spin_unlock_irqrestore(&wc->reglock, flags); + return 0; +} + +static int t1xxp_chanconfig(struct zt_chan *chan, int sigtype) +{ + struct t1 *wc = chan->pvt; + int alreadyrunning = chan->span->flags & ZT_FLAG_RUNNING; + + if (alreadyrunning && (wc->spantype != TYPE_E1)) + __t1xxp_set_clear(wc, chan->channo); + + return 0; +} + +static int t1xxp_spanconfig(struct zt_span *span, struct zt_lineconfig *lc) +{ + struct t1 *wc = span->pvt; + + /* Do we want to SYNC on receive or not */ + wc->sync = lc->sync; + if (wc->sync) + wc->ctlreg |= 0x80; + else + wc->ctlreg &= ~0x80; + + /* If already running, apply changes immediately */ + if (span->flags & ZT_FLAG_RUNNING) + return t1xxp_startup(span); + + return 0; +} + +static int t1xxp_rbsbits(struct zt_chan *chan, int bits) +{ + u_char m,c; + int n,b; + struct t1 *wc = chan->pvt; + unsigned long flags; + + debug_printk(2, "Setting bits to %d on channel %s\n", bits, chan->name); + if (wc->spantype == TYPE_E1) { /* do it E1 way */ + if (chan->chanpos == 16) + return 0; + + n = chan->chanpos - 1; + if (chan->chanpos > 15) n--; + b = (n % 15); + spin_lock_irqsave(&wc->reglock, flags); + c = wc->txsigs[b]; + m = (n / 15) << 2; /* nibble selector */ + c &= (0xf << m); /* keep the other nibble */ + c |= (bits & 0xf) << (4 - m); /* put our new nibble here */ + wc->txsigs[b] = c; + spin_unlock_irqrestore(&wc->reglock, flags); + /* output them to the chip */ + t1_setreg_full(wc,0x71 + b,c,1,NOT_VPM); + } else if (wc->span.lineconfig & ZT_CONFIG_D4) { + n = chan->chanpos - 1; + b = (n / 4); + spin_lock_irqsave(&wc->reglock, flags); + c = wc->txsigs[b]; + m = ((3 - (n % 4)) << 1); /* nibble selector */ + c &= ~(0x3 << m); /* keep the other nibble */ + c |= ((bits >> 2) & 0x3) << m; /* put our new nibble here */ + wc->txsigs[b] = c; + spin_unlock_irqrestore(&wc->reglock, flags); + /* output them to the chip */ + t1_setreg_full(wc,0x70 + b,c,1,NOT_VPM); + t1_setreg_full(wc,0x70 + b + 6,c,1,NOT_VPM); + } else if (wc->span.lineconfig & ZT_CONFIG_ESF) { + n = chan->chanpos - 1; + b = (n / 2); + spin_lock_irqsave(&wc->reglock, flags); + c = wc->txsigs[b]; + m = ((n % 2) << 2); /* nibble selector */ + c &= (0xf << m); /* keep the other nibble */ + c |= (bits & 0xf) << (4 - m); /* put our new nibble here */ + wc->txsigs[b] = c; + spin_unlock_irqrestore(&wc->reglock, flags); + /* output them to the chip */ + t1_setreg_full(wc,0x70 + b,c,1,NOT_VPM); + } + debug_printk(2,"Finished setting RBS bits\n"); + + return 0; +} + +static inline void __t1_check_sigbits_reads(struct t1 *wc) +{ + int i; + + if (!(wc->span.flags & ZT_FLAG_RUNNING)) + return; + if (wc->spantype == TYPE_E1) { + for (i = 0; i < 15; i++) { + if (t1_getreg(wc, 0x71 + i, 1)) + wc->isrreaderrors++; + } + } else if (wc->span.lineconfig & ZT_CONFIG_D4) { + for (i = 0; i < 24; i+=4) { + if (t1_getreg(wc, 0x70 + (i >> 2), 1)) + wc->isrreaderrors++; + } + } else { + for (i = 0; i < 24; i+=2) { + if (t1_getreg(wc, 0x70 + (i >> 1), 1)) + wc->isrreaderrors++; + } + } +} + +static inline void __t1_check_sigbits(struct t1 *wc) +{ + int a,i,rxs; + + if (!(wc->span.flags & ZT_FLAG_RUNNING)) + return; + if (wc->spantype == TYPE_E1) { + for (i = 0; i < 15; i++) { + a = t1_getreg_isr(wc, 0x71 + i); + if (a > -1) { + /* Get high channel in low bits */ + rxs = (a & 0xf); + if (!(wc->span.chans[i+16].sig & ZT_SIG_CLEAR)) { + if (wc->span.chans[i+16].rxsig != rxs) { + spin_unlock(&wc->reglock); + zt_rbsbits(&wc->span.chans[i+16], rxs); + spin_lock(&wc->reglock); + } + } + rxs = (a >> 4) & 0xf; + if (!(wc->span.chans[i].sig & ZT_SIG_CLEAR)) { + if (wc->span.chans[i].rxsig != rxs) { + spin_unlock(&wc->reglock); + zt_rbsbits(&wc->span.chans[i], rxs); + spin_lock(&wc->reglock); + } + } + } else { + debug_printk(1, "no space to request register in isr\n"); + } + } + } else if (wc->span.lineconfig & ZT_CONFIG_D4) { + for (i = 0; i < 24; i+=4) { + a = t1_getreg_isr(wc, 0x70 + (i>>2)); + if (a > -1) { + /* Get high channel in low bits */ + rxs = (a & 0x3) << 2; + if (!(wc->span.chans[i+3].sig & ZT_SIG_CLEAR)) { + if (wc->span.chans[i+3].rxsig != rxs) { + spin_unlock(&wc->reglock); + zt_rbsbits(&wc->span.chans[i+3], rxs); + spin_lock(&wc->reglock); + } + } + rxs = (a & 0xc); + if (!(wc->span.chans[i+2].sig & ZT_SIG_CLEAR)) { + if (wc->span.chans[i+2].rxsig != rxs) { + spin_unlock(&wc->reglock); + zt_rbsbits(&wc->span.chans[i+2], rxs); + spin_lock(&wc->reglock); + } + } + rxs = (a >> 2) & 0xc; + if (!(wc->span.chans[i+1].sig & ZT_SIG_CLEAR)) { + if (wc->span.chans[i+1].rxsig != rxs) { + spin_unlock(&wc->reglock); + zt_rbsbits(&wc->span.chans[i+1], rxs); + spin_lock(&wc->reglock); + } + } + rxs = (a >> 4) & 0xc; + if (!(wc->span.chans[i].sig & ZT_SIG_CLEAR)) { + if (wc->span.chans[i].rxsig != rxs) { + spin_unlock(&wc->reglock); + zt_rbsbits(&wc->span.chans[i], rxs); + spin_lock(&wc->reglock); + } + } + } + } + } else { + for (i = 0; i < 24; i+=2) { + a = t1_getreg_isr(wc, 0x70 + (i>>1)); + if (a > -1) { + /* Get high channel in low bits */ + rxs = (a & 0xf); + if (!(wc->span.chans[i+1].sig & ZT_SIG_CLEAR)) { + if (wc->span.chans[i+1].rxsig != rxs) { + spin_unlock(&wc->reglock); + zt_rbsbits(&wc->span.chans[i+1], rxs); + spin_lock(&wc->reglock); + } + } + rxs = (a >> 4) & 0xf; + if (!(wc->span.chans[i].sig & ZT_SIG_CLEAR)) { + if (wc->span.chans[i].rxsig != rxs) { + spin_unlock(&wc->reglock); + zt_rbsbits(&wc->span.chans[i], rxs); + spin_lock(&wc->reglock); + } + } + } + } + } +} + +static int t1xxp_maint(struct zt_span *span, int cmd) +{ + struct t1 *wc = span->pvt; + + if (wc->spantype == TYPE_E1) { + switch (cmd) { + case ZT_MAINT_NONE: + module_printk("XXX Turn off local and remote loops E1 XXX\n"); + break; + case ZT_MAINT_LOCALLOOP: + module_printk("XXX Turn on local loopback E1 XXX\n"); + break; + case ZT_MAINT_REMOTELOOP: + module_printk("XXX Turn on remote loopback E1 XXX\n"); + break; + case ZT_MAINT_LOOPUP: + module_printk("XXX Send loopup code E1 XXX\n"); + break; + case ZT_MAINT_LOOPDOWN: + module_printk("XXX Send loopdown code E1 XXX\n"); + break; + case ZT_MAINT_LOOPSTOP: + module_printk("XXX Stop sending loop codes E1 XXX\n"); + break; + default: + module_printk("Unknown E1 maint command: %d\n", cmd); + break; + } + } else { + switch (cmd) { + case ZT_MAINT_NONE: + module_printk("XXX Turn off local and remote loops T1 XXX\n"); + break; + case ZT_MAINT_LOCALLOOP: + module_printk("XXX Turn on local loop and no remote loop XXX\n"); + break; + case ZT_MAINT_REMOTELOOP: + module_printk("XXX Turn on remote loopup XXX\n"); + break; + case ZT_MAINT_LOOPUP: + t1_setreg(wc, 0x21, 0x50); /* FMR5: Nothing but RBS mode */ + break; + case ZT_MAINT_LOOPDOWN: + t1_setreg(wc, 0x21, 0x60); /* FMR5: Nothing but RBS mode */ + break; + case ZT_MAINT_LOOPSTOP: + t1_setreg(wc, 0x21, 0x40); /* FMR5: Nothing but RBS mode */ + break; + default: + module_printk("Unknown T1 maint command: %d\n", cmd); + break; + } + } + + return 0; +} + +static int t1xxp_open(struct zt_chan *chan) +{ + struct t1 *wc = chan->pvt; + + if (wc->dead) + return -ENODEV; + wc->usecount++; + +#ifndef LINUX26 + MOD_INC_USE_COUNT; +#else + try_module_get(THIS_MODULE); +#endif + + return 0; +} + +static int t1xxp_close(struct zt_chan *chan) +{ + struct t1 *wc = chan->pvt; + + wc->usecount--; + +#ifndef LINUX26 + MOD_DEC_USE_COUNT; +#else + module_put(THIS_MODULE); +#endif + + /* If we're dead, release us now */ + if (!wc->usecount && wc->dead) + t1_release(wc); + + return 0; +} + +static int t1xxp_ioctl(struct zt_chan *chan, unsigned int cmd, unsigned long data) +{ + struct t4_regs regs; + unsigned int x; + struct t1 *wc = chan->pvt; + + switch (cmd) { + case WCT4_GET_REGS: + wc = chan->pvt; + for (x = 0; x < sizeof(regs.pci) / sizeof(regs.pci[0]); x++) +#if 1 + regs.pci[x] = (inb(wc->iobase + (x << 2))) | + (inb(wc->iobase + (x << 2) + 1) << 8) | + (inb(wc->iobase + (x << 2) + 2) << 16) | + (inb(wc->iobase + (x << 2) + 3) << 24); +#else + regs.pci[x] = (inb(wc->iobase + x)); +#endif + + for (x = 0; x < sizeof(regs.regs) / sizeof(regs.regs[0]); x++) + regs.regs[x] = t1_getreg(wc, x, 0); + + if (copy_to_user((struct t4_regs *) data, ®s, sizeof(regs))) + return -EFAULT; + break; +#ifdef VPM_SUPPORT + case ZT_TONEDETECT: + if (get_user(x, (int *) data)) + return -EFAULT; + if (!wc->vpm150m) + return -ENOSYS; + if (wc->vpm150m && (x && !vpmdtmfsupport)) + return -ENOSYS; + if (x & ZT_TONEDETECT_ON) { + set_bit(chan->chanpos - 1, &wc->dtmfmask); + module_printk("turning on tone detection\n"); + } else { + clear_bit(chan->chanpos - 1, &wc->dtmfmask); + module_printk("turning off tone detection\n"); + } + if (x & ZT_TONEDETECT_MUTE) { + if(wc->vpm150m) + set_bit(chan->chanpos - 1, &wc->vpm150m->desireddtmfmutestate); + } else { + if(wc->vpm150m) + clear_bit(chan->chanpos - 1, &wc->vpm150m->desireddtmfmutestate); + } + return 0; +#endif + default: + return -ENOTTY; + } + return 0; +} + +#ifdef VPM_SUPPORT + +#include "adt_lec.c" + +static int t1xxp_echocan_with_params(struct zt_chan *chan, struct zt_echocanparams *ecp, struct zt_echocanparam *p) +{ + struct adt_lec_params params; + struct t1 *wc = chan->pvt; + struct vpm150m *vpm150m = wc->vpm150m; + unsigned int flags; + struct vpm150m_workentry *work; + unsigned int ret; + + if (!wc->vpm150m) + return -ENODEV; + + adt_lec_init_defaults(¶ms, 32); + + if ((ret = adt_lec_parse_params(¶ms, ecp, p))) + return ret; + + /* we can't really control the tap length, but the value is used + to control whether the ec is on or off, so translate it */ + params.tap_length = ecp->tap_length ? 1 : 0; + + if (!(work = kmalloc(sizeof(*work), GFP_KERNEL))) + return -ENOMEM; + + work->params = params; + work->wc = wc; + work->chan = chan; + spin_lock_irqsave(&vpm150m->lock, flags); + list_add_tail(&work->list, &vpm150m->worklist); + spin_unlock_irqrestore(&vpm150m->lock, flags); + + /* we must do this later since we cannot sleep in the echocan function */ + if (test_bit(VPM150M_ACTIVE, &vpm150m->control)) + queue_work(vpm150m->wq, &vpm150m->work_echocan); + + return 0; /* how do I return the status since it is done later by the workqueue? */ +} +#endif + +static int t1_software_init(struct t1 *wc) +{ + int x; + + /* Find position */ + for (x = 0; x < sizeof(ifaces) / sizeof(ifaces[0]); x++) { + if (ifaces[x] == wc) { + debug_printk(1, "software init for card %d\n",x); + break; + } + } + + if (x == sizeof(ifaces) / sizeof(ifaces[0])) + return -1; + + t4_serial_setup(wc); + + wc->num = x; + sprintf(wc->span.name, "WCT1/%d", wc->num); + snprintf(wc->span.desc, sizeof(wc->span.desc) - 1, "%s Card %d", wc->variety, wc->num); + wc->span.manufacturer = "Digium"; + strncpy(wc->span.devicetype, wc->variety, sizeof(wc->span.devicetype) - 1); + +#if defined(VPM_SUPPORT) + if (wc->vpm150m) + strncat(wc->span.devicetype, " with VPMADT032", sizeof(wc->span.devicetype) - 1); +#endif + + snprintf(wc->span.location, sizeof(wc->span.location) - 1, + "PCI Bus %02d Slot %02d", wc->dev->bus->number, PCI_SLOT(wc->dev->devfn) + 1); + + wc->span.spanconfig = t1xxp_spanconfig; + wc->span.chanconfig = t1xxp_chanconfig; + wc->span.irq = wc->dev->irq; + 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.ioctl = t1xxp_ioctl; +#ifdef VPM_SUPPORT + wc->span.echocan_with_params = t1xxp_echocan_with_params; +#endif + + if (wc->spantype == TYPE_E1) { + if (unchannelized) + wc->span.channels = 32; + else + wc->span.channels = 31; + wc->span.spantype = "E1"; + wc->span.linecompat = ZT_CONFIG_HDB3 | ZT_CONFIG_CCS | ZT_CONFIG_CRC4; + wc->span.deflaw = ZT_LAW_ALAW; + } else { + wc->span.channels = 24; + wc->span.spantype = "T1"; + wc->span.linecompat = ZT_CONFIG_AMI | ZT_CONFIG_B8ZS | ZT_CONFIG_D4 | ZT_CONFIG_ESF; + wc->span.deflaw = ZT_LAW_MULAW; + } + wc->span.chans = wc->chans; + wc->span.flags = ZT_FLAG_RBS; + wc->span.pvt = wc; + init_waitqueue_head(&wc->span.maintq); + for (x = 0; x < wc->span.channels; 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_EM_E1 | + ZT_SIG_FXSLS | ZT_SIG_FXSGS | + ZT_SIG_FXSKS | ZT_SIG_FXOLS | ZT_SIG_DACS_RBS | + ZT_SIG_FXOGS | ZT_SIG_FXOKS | ZT_SIG_CAS | ZT_SIG_SF; + wc->chans[x].pvt = wc; + wc->chans[x].chanpos = x + 1; + } + if (zt_register(&wc->span, 0)) { + module_printk("Unable to register span with Zaptel\n"); + return -1; + } + wc->initialized = 1; + + return 0; +} + +#ifdef VPM_SUPPORT +static inline unsigned char t1_vpm_in(struct t1 *wc, int unit, const unsigned int addr) +{ + return t1_getreg_full(wc, addr, 0, unit); +} + +static inline unsigned char t1_vpm_out(struct t1 *wc, int unit, const unsigned int addr, const unsigned char val) +{ + return t1_setreg_full(wc, addr, val, 0, unit); +} + +#endif + +static int t1_hardware_post_init(struct t1 *wc) +{ + unsigned int reg; + int x; + + /* T1 or E1 */ + if (t1e1override > -1) { + if (t1e1override) + wc->spantype = TYPE_E1; + else + wc->spantype = TYPE_T1; + } else { + if (t1_getpins(wc,0) & 0x01) /* returns 1 for T1 mode */ + wc->spantype = TYPE_T1; + else + wc->spantype = TYPE_E1; + } + debug_printk(1, "spantype: %s\n", wc->spantype==1 ? "T1" : "E1"); + + if (wc->spantype == TYPE_E1) { + if (unchannelized) + wc->chanmap = chanmap_e1uc; + else + wc->chanmap = chanmap_e1; + } else + wc->chanmap = chanmap_t1; + /* what version of the FALC are we using? */ + reg = t1_setreg(wc, 0x4a, 0xaa); + reg = t1_getreg(wc, 0x4a, 0); + debug_printk(1, "FALC version: %08x\n", reg); + + /* make sure reads and writes work */ + for (x = 0; x < 256; x++) { + t1_setreg(wc, 0x14, x); + if ((reg = t1_getreg(wc, 0x14, 0)) != x) + module_printk("Wrote '%x' but read '%x'\n", x, reg); + } + + /* all LED's blank */ + wc->ledtestreg = UNSET_LED_ORANGE(wc->ledtestreg); + wc->ledtestreg = UNSET_LED_REDGREEN(wc->ledtestreg); + t1_setleds(wc, wc->ledtestreg, 0); + +#ifdef VPM_SUPPORT + t1_vpm150m_init(wc); + if (wc->vpm150m) { + module_printk("VPM present and operational (Firmware version %x)\n", wc->vpm150m->version); + wc->ctlreg |= 0x10; /* turn on vpm (RX audio from vpm module) */ + if (vpmtsisupport) { + debug_printk(1, "enabling VPM TSI pin\n"); + wc->ctlreg |= 0x01; /* turn on vpm timeslot interchange pin */ + } + } +#endif + + return 0; +} + +static inline void __t1_check_alarms_reads(struct t1 *wc) +{ + if (!(wc->span.flags & ZT_FLAG_RUNNING)) + return; + + if (t1_getreg(wc, 0x4c, 1)) + wc->isrreaderrors++; + if (t1_getreg(wc, 0x20, 1)) + wc->isrreaderrors++; + if (t1_getreg(wc, 0x4d, 1)) + wc->isrreaderrors++; +} + +static inline void __t1_check_alarms(struct t1 *wc) +{ + unsigned char c,d; + int alarms; + int x,j; + unsigned char fmr4; /* must read this always */ + + if (!(wc->span.flags & ZT_FLAG_RUNNING)) + return; + + c = t1_getreg_isr(wc, 0x4c); + fmr4 = t1_getreg_isr(wc, 0x20); /* must read this even if we don't use it */ + d = t1_getreg_isr(wc, 0x4d); + + /* Assume no alarms */ + alarms = 0; + + /* And consider only carrier alarms */ + wc->span.alarms &= (ZT_ALARM_RED | ZT_ALARM_BLUE | ZT_ALARM_NOTOPEN); + + if (wc->spantype == TYPE_E1) { + if (c & 0x04) { + /* No multiframe found, force RAI high after 400ms only if + we haven't found a multiframe since last loss + of frame */ + if (!wc->flags.nmf) { + t1_setreg_full(wc, 0x20, 0x9f | 0x20, 1, NOT_VPM); /* LIM0: Force RAI High */ + wc->flags.nmf = 1; + module_printk("NMF workaround on!\n"); + } + t1_setreg_full(wc, 0x1e, 0xc3, 1, NOT_VPM); /* Reset to CRC4 mode */ + t1_setreg_full(wc, 0x1c, 0xf2, 1, NOT_VPM); /* Force Resync */ + t1_setreg_full(wc, 0x1c, 0xf0, 1, NOT_VPM); /* Force Resync */ + } else if (!(c & 0x02)) { + if (wc->flags.nmf) { + t1_setreg_full(wc, 0x20, 0x9f, 1, NOT_VPM); /* LIM0: Clear forced RAI */ + wc->flags.nmf = 0; + module_printk("NMF workaround off!\n"); + } + } + } else { + /* Detect loopup code if we're not sending one */ + if ((!wc->span.mainttimer) && (d & 0x08)) { + /* Loop-up code detected */ + if ((wc->loopupcnt++ > 80) && (wc->span.maintstat != ZT_MAINT_REMOTELOOP)) { + t1_setreg_full(wc, 0x36, 0x08, 1, NOT_VPM); /* LIM0: Disable any local loop */ + t1_setreg_full(wc, 0x37, 0xf6, 1, NOT_VPM); /* LIM1: Enable remote loop */ + wc->span.maintstat = ZT_MAINT_REMOTELOOP; + } + } else + wc->loopupcnt = 0; + /* Same for loopdown code */ + if ((!wc->span.mainttimer) && (d & 0x10)) { + /* Loop-down code detected */ + if ((wc->loopdowncnt++ > 80) && (wc->span.maintstat == ZT_MAINT_REMOTELOOP)) { + t1_setreg_full(wc, 0x36, 0x08, 1, NOT_VPM); /* LIM0: Disable any local loop */ + t1_setreg_full(wc, 0x37, 0xf0, 1, NOT_VPM); /* LIM1: Disable remote loop */ + wc->span.maintstat = ZT_MAINT_NONE; + } + } else + wc->loopdowncnt = 0; + } + + if (wc->span.lineconfig & ZT_CONFIG_NOTOPEN) { + for (x=0,j=0;x < wc->span.channels;x++) + if ((wc->span.chans[x].flags & ZT_FLAG_OPEN) || + (wc->span.chans[x].flags & ZT_FLAG_NETDEV)) + j++; + if (!j) + alarms |= ZT_ALARM_NOTOPEN; + } + + if (c & 0xa0) { + if (wc->alarmcount >= alarmdebounce) { + if (!unchannelized) + alarms |= ZT_ALARM_RED; + } else + wc->alarmcount++; + } else + wc->alarmcount = 0; + if (c & 0x4) + 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->flags.sendingyellow) { + module_printk("Setting yellow alarm\n"); + + /* We manually do yellow alarm to handle RECOVER and NOTOPEN, otherwise it's auto anyway */ + t1_setreg_full(wc, 0x20, fmr4 | 0x20, 1, NOT_VPM); + wc->flags.sendingyellow = 1; + } else if (!alarms && wc->flags.sendingyellow) { + module_printk("Clearing yellow alarm\n"); + /* We manually do yellow alarm to handle RECOVER */ + t1_setreg_full(wc, 0x20, fmr4 & ~0x20, 1, NOT_VPM); + wc->flags.sendingyellow = 0; + } + + if ((c & 0x10) && !unchannelized) + alarms |= ZT_ALARM_YELLOW; + if (wc->span.mainttimer || wc->span.maintstat) + alarms |= ZT_ALARM_LOOPBACK; + wc->span.alarms = alarms; + spin_unlock(&wc->reglock); + zt_alarm_notify(&wc->span); + spin_lock(&wc->reglock); +} + +static inline void __handle_leds(struct t1 *wc) +{ + if (wc->span.alarms & (ZT_ALARM_RED | ZT_ALARM_BLUE)) { + wc->blinktimer++; + if (wc->blinktimer == 160) + wc->ledtestreg = SET_LED_RED(wc->ledtestreg); + if (wc->blinktimer == 480) { + wc->ledtestreg = UNSET_LED_REDGREEN(wc->ledtestreg); + wc->blinktimer = 0; + } + } else if (wc->span.alarms & ZT_ALARM_YELLOW) { + wc->yellowtimer++; + if (!(wc->yellowtimer % 2)) + wc->ledtestreg = SET_LED_RED(wc->ledtestreg); + else + wc->ledtestreg = SET_LED_GREEN(wc->ledtestreg); + } else { + if (wc->span.maintstat != ZT_MAINT_NONE) + wc->ledtestreg = SET_LED_ORANGE(wc->ledtestreg); + else + wc->ledtestreg = UNSET_LED_ORANGE(wc->ledtestreg); + if (wc->span.flags & ZT_FLAG_RUNNING) + wc->ledtestreg = SET_LED_GREEN(wc->ledtestreg); + else + wc->ledtestreg = UNSET_LED_REDGREEN(wc->ledtestreg); + } + + if (wc->ledtestreg != wc->ledlastvalue) { + t1_setleds(wc, wc->ledtestreg, 1); + wc->ledlastvalue = wc->ledtestreg; + } +} + + +static void __t1_do_counters(struct t1 *wc) +{ + if (wc->alarmtimer) { + if (!--wc->alarmtimer) { + wc->span.alarms &= ~(ZT_ALARM_RECOVER); + zt_alarm_notify(&wc->span); + } + } +} + +static inline void t1_isr_misc(struct t1 *wc) +{ + unsigned int x; + + if (unlikely(!wc->initialized)) return; + + __handle_leds(wc); + + __t1_do_counters(wc); + + x = wc->intcount & 0xF; + switch (x) { + case 0: + __t1_check_sigbits_reads(wc); + break; + case 1: + if (!(wc->intcount & 0x30)) { + __t1_check_alarms_reads(wc); + wc->alarms_read=1; + } + break; + case 2: + break; + case 4: + break; + case 5: + break; + case 7: + __t1_check_sigbits(wc); + break; + case 8: + if (wc->alarms_read) { + __t1_check_alarms(wc); + wc->alarms_read=0; + } + break; + case 9: + clean_leftovers(wc); + break; + } +} + +static inline void t1_transmitprep(struct t1 *wc, int dbl) +{ + volatile unsigned char *writechunk; + int x; + int y; + int chan; + + dbl = dbl % 2; + + writechunk = (volatile unsigned char *)(wc->writechunk); + if (dbl) + /* Write is at interrupt address. Start writing from normal offset */ + writechunk += SFRAME_SIZE; + + /* Calculate Transmission */ + if (likely(wc->initialized)) { + spin_unlock(&wc->reglock); + zt_transmit(&wc->span); + spin_lock(&wc->reglock); + } + + for (x = 0; x < ZT_CHUNKSIZE; x++) { + if (likely(wc->initialized)) { + for (chan = 0; chan < wc->span.channels; chan++) + writechunk[(chan+1)*2] = wc->chans[chan].writechunk[x]; + } + + /* process the command queue */ + for (y = 0; y < 7; y++) { + cmd_dequeue(wc, writechunk, x, y); + } +#ifdef VPM_SUPPORT + if(likely(wc->vpm150m)) { + vpm150m_cmd_dequeue(wc, writechunk, x); + } +#endif + + if (x < ZT_CHUNKSIZE - 1) { + writechunk[EFRAME_SIZE] = wc->ctlreg; + writechunk[EFRAME_SIZE + 1] = wc->txident++; + } + writechunk += (EFRAME_SIZE + EFRAME_GAP); + } +} + +static inline void cmd_retransmit(struct t1 *wc) +{ + unsigned int x; + + for (x = 0; x < sizeof(wc->cmdq.cmds) / sizeof(wc->cmdq.cmds[0]); x++) { + if (!(wc->cmdq.cmds[x].flags & __CMD_FIN)) { + wc->cmdq.cmds[x].flags &= ~(__CMD_TX) ; /* clear __CMD_TX */ + wc->cmdq.cmds[x].ident = 0; + } + } +} + +static inline void t1_receiveprep(struct t1 *wc, int dbl) +{ + volatile unsigned char *readchunk; + int x,chan; + unsigned char expected; + + dbl = dbl % 2; + + readchunk = (volatile unsigned char *)wc->readchunk; + if (dbl) + readchunk += SFRAME_SIZE; + for (x = 0; x < ZT_CHUNKSIZE; x++) { + if (likely(wc->initialized)) { + for (chan = 0; chan < wc->span.channels; chan++) { + wc->chans[chan].readchunk[x]= readchunk[(chan+1)*2]; + } + } + if (x < ZT_CHUNKSIZE - 1) { + expected = wc->rxident+1; + wc->rxident = readchunk[EFRAME_SIZE + 1]; + wc->statreg = readchunk[EFRAME_SIZE + 2]; + if (wc->rxident != expected) { + wc->span.irqmisses++; + cmd_retransmit(wc); + if (unlikely(debug && wc->initialized)) + module_printk("oops: rxident=%d expected=%d\n", wc->rxident, expected); + } + } + cmd_decipher(wc, readchunk); +#ifdef VPM_SUPPORT + if(wc->vpm150m) + vpm150m_cmd_decipher(wc, readchunk); +#endif + readchunk += (EFRAME_SIZE + EFRAME_GAP); + } + + /* echo cancel */ + if (likely(wc->initialized)) { + spin_unlock(&wc->reglock); + for (x = 0; x < wc->span.channels; x++) { + zt_ec_chunk(&wc->chans[x], wc->chans[x].readchunk, wc->ec_chunk2[x]); + memcpy(wc->ec_chunk2[x],wc->ec_chunk1[x],ZT_CHUNKSIZE); + memcpy(wc->ec_chunk1[x],wc->chans[x].writechunk,ZT_CHUNKSIZE); + } + zt_receive(&wc->span); + spin_lock(&wc->reglock); + } + + /* Wake up anyone sleeping to read/write a new register */ + wake_up_interruptible(&wc->regq); +} + +static inline int t1_check_descriptor(struct t1 *wc, int tx) +{ + int o2 = 0; + + if (!tx) { + o2 += ERING_SIZE * 4; + o2 += wc->rdbl * 4; + } else { + o2 += wc->tdbl * 4; + } + + if (!(wc->descripchunk[o2] & 0x80000000)) { + if (tx) { + wc->txints++; + t1_transmitprep(wc, wc->tdbl); + t1_reinit_descriptor(wc, tx, wc->tdbl, "txchk"); + wc->tdbl = (wc->tdbl + 1) % ERING_SIZE; + wc->intcount++; + t1_isr_misc(wc); + } else { + wc->rxints++; + t1_receiveprep(wc, wc->rdbl); + t1_reinit_descriptor(wc, tx, wc->rdbl, "rxchk"); + wc->rdbl = (wc->rdbl + 1) % ERING_SIZE; + } + return 1; + } + return 0; +} + +static int t1_hardware_init(struct t1 *wc) +{ + /* Hardware stuff */ + unsigned int reg; + unsigned long newjiffies; + + /* Initialize descriptors */ + t1_init_descriptors(wc); + + /* Enable I/O Access */ + pci_read_config_dword(wc->dev, PCI_COMMAND, ®); + reg |= PCI_COMMAND_IO | PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER; + pci_write_config_dword(wc->dev, PCI_COMMAND, reg); + debug_printk(1, "PCI Config reg is %08x\n", reg); + + t1_setctl(wc, 0x0000, 0xfff88001); + + newjiffies = jiffies + HZ/10; + while(((reg = t1_getctl(wc,0x0000)) & 0x00000001) && ( time_after(newjiffies,jiffies) )); + debug_printk(1, "ctlreg 0x0000 now=%08x!\n", reg); + + t1_setctl(wc, 0x0000, 0xfff88000); + + /* Configure watchdogs, access, etc */ + t1_setctl(wc, 0x0030, 0x00280048); + t1_setctl(wc, 0x0078, 0x00000013 /* | (1 << 28) */); + + reg = t1_getctl(wc, 0x00fc); + t1_setctl(wc, 0x00fc, (reg & ~0x7) | 0x7); /* normal mode */ + t1_setsdi(wc, 0x00, 0x0100); + t1_setsdi(wc, 0x16, 0x2100); + debug_printk(1, "Detected SDI REG0: %08x\n", t1_getsdi(wc, 0x00)); + debug_printk(1, "Detected SDI REG1: %08x\n", t1_getsdi(wc, 0x01)); + debug_printk(1, "Detected SDI REG2: %08x\n", t1_getsdi(wc, 0x02)); + + reg = t1_getctl(wc, 0x00fc); + debug_printk(1, "(pre) Reg fc is %08x\n", reg); + + t1_setctl(wc, 0x00fc, (reg & ~0x7) | 0x4); /* mac only */ + t1_setsdi(wc, 0x00, 0x0100); /* full duplex */ + t1_setsdi(wc, 0x16, 0x2100); + reg = t1_getctl(wc, 0x00fc); + debug_printk(1, "(post) ctlreg 0xfc=%08x\n", reg); + debug_printk(1, "Detected SDI REG2: %08x\n", t1_getsdi(wc, 0x02)); + debug_printk(1, "ctlreg 0x0088=%08x\n", t1_getctl(wc, 0x0088)); + + return 0; +} + + +ZAP_IRQ_HANDLER(te12xp_interrupt) +{ + struct t1 *wc = dev_id; + unsigned int ints; + int res; + + /* Read interrupts */ + spin_lock(&wc->reglock); + ints = __t1_getctl(wc, 0x0028); + + if (!ints) { + spin_unlock(&wc->reglock); +#ifdef LINUX26 + return IRQ_NONE; +#else + return; +#endif + } + + /* clear interrupts interrupts (we only get here if interrupt is for us) */ + __t1_setctl(wc, 0x0028, ints); + ints &= wc->intmask; + + if (ints & 0x00000041) { + do { + res = t1_check_descriptor(wc, 0); + res |= t1_check_descriptor(wc, 1); + } while(res); + } + spin_unlock(&wc->reglock); + +#ifdef LINUX26 + return IRQ_RETVAL(1); +#endif +} + +static int __devinit te12xp_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) +{ + struct t1 *wc; + struct t1_desc *d = (struct t1_desc *) ent->driver_data; + unsigned int x; + + for (x = 0; x < sizeof(ifaces) / sizeof(ifaces[0]); x++) + if (!ifaces[x]) break; + + if (x >= sizeof(ifaces) / sizeof(ifaces[0])) { + module_printk("Too many interfaces\n"); + return -EIO; + } + + if (pci_enable_device(pdev)) + return -EIO; + + wc = kmalloc(sizeof(*wc), GFP_KERNEL); + if (!wc) + return -ENOMEM; + + ifaces[x] = wc; + memset(wc, 0, sizeof(*wc)); + spin_lock_init(&wc->reglock); + wc->iobase = pci_resource_start(pdev, 0); + wc->dev = pdev; + wc->variety = d->name; + /* Keep track of whether we need to free the region */ + if (request_region(wc->iobase, 0xff, te12xp_driver.name)) + wc->freeregion = 1; + + /* Allocate enough memory for two zt chunks, receive and transmit. + * Each sample uses 32 bits. Allocate an extra set just for + * control too */ + wc->writechunk = (int *) pci_alloc_consistent(pdev, PCI_WINDOW_SIZE, &wc->writedma); + if (!wc->writechunk) { + module_printk("Unable to allocate DMA-able memory\n"); + if (wc->freeregion) + release_region(wc->iobase, 0xff); + kfree(wc); + return -ENOMEM; + } + + wc->readchunk = wc->writechunk + SFRAME_SIZE / 2; /* in doublewords */ + wc->readdma = wc->writedma + SFRAME_SIZE * 2; /* in bytes */ + + wc->descripchunk = wc->readchunk + SFRAME_SIZE / 2; /* in doublewords */ + wc->descripdma = wc->readdma + SFRAME_SIZE * 2; /* in bytes */ + + /* Initialize Write/Buffers to all blank data */ + memset((void *)wc->writechunk, 0x00, SFRAME_SIZE * 2); + memset((void *)wc->readchunk, 0x00, SFRAME_SIZE * 2); + + init_waitqueue_head(&wc->regq); + + /* Enable bus mastering */ + pci_set_master(pdev); + + /* Keep track of which device we are */ + pci_set_drvdata(pdev, wc); + + if (request_irq(pdev->irq, te12xp_interrupt, ZAP_IRQ_SHARED, te12xp_driver.name, wc)) { + module_printk("Unable to request IRQ %d\n", pdev->irq); + if (wc->freeregion) + release_region(wc->iobase, 0xff); + pci_free_consistent(pdev, PCI_WINDOW_SIZE, (void *) wc->writechunk, wc->writedma); + pci_set_drvdata(pdev, NULL); + kfree(wc); + return -EIO; + } + + if (t1_hardware_init(wc)) { + /* Set Reset Low */ + t1_stop_dma(wc); + /* Free Resources */ + free_irq(pdev->irq, wc); + if (wc->freeregion) + release_region(wc->iobase, 0xff); + pci_free_consistent(pdev, PCI_WINDOW_SIZE, (void *) wc->writechunk, wc->writedma); + pci_set_drvdata(pdev, NULL); + + kfree(wc); + return -EIO; + + } + + t1_enable_interrupts(wc); + t1_start_dma(wc); + t1_hardware_post_init(wc); + t1_software_init(wc); + module_printk("Found a %s\n", wc->variety); + + return 0; +} + +static void __devexit te12xp_remove_one(struct pci_dev *pdev) +{ + struct t1 *wc = pci_get_drvdata(pdev); +#ifdef VPM_SUPPORT + unsigned long flags; + struct vpm150m *vpm150m = wc->vpm150m; +#endif + if (!wc) + return; + +#ifdef VPM_SUPPORT + if(vpm150m) { + clear_bit(VPM150M_DTMFDETECT, &vpm150m->control); + clear_bit(VPM150M_ACTIVE, &vpm150m->control); + flush_workqueue(vpm150m->wq); + destroy_workqueue(vpm150m->wq); + } +#endif + /* Stop any DMA */ + t1_stop_dma(wc); + + /* In case hardware is still there */ + t1_disable_interrupts(wc); + + if (debug && wc->isrreaderrors) + debug_printk(1, "isrreaderrors=%d\n", wc->isrreaderrors); + + /* Immediately free resources */ + free_irq(pdev->irq, wc); + pci_free_consistent(pdev, PCI_WINDOW_SIZE, (void *)wc->writechunk, wc->writedma); + +#ifdef VPM_SUPPORT + if(vpm150m) { + spin_lock_irqsave(&wc->reglock, flags); + wc->vpm150m = NULL; + vpm150m->wc = NULL; + spin_unlock_irqrestore(&wc->reglock, flags); + kfree(wc->vpm150m); + } +#endif + /* Release span, possibly delayed */ + if (!wc->usecount) + t1_release(wc); + else + wc->dead = 1; +} + +static struct pci_device_id te12xp_pci_tbl[] = { + { 0xd161, 0x0120, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (unsigned long) &te120p}, + { 0xd161, 0x8000, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (unsigned long) &te121}, + { 0xd161, 0x8001, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (unsigned long) &te122}, + { 0 } +}; + +MODULE_DEVICE_TABLE(pci, te12xp_pci_tbl); + +struct pci_driver te12xp_driver = { + name: "wcte12x[p]", + probe: te12xp_init_one, +#ifdef LINUX26 + remove: __devexit_p(te12xp_remove_one), +#else + remove: te12xp_remove_one, +#endif + suspend: NULL, + resume: NULL, + id_table: te12xp_pci_tbl, +}; + +static int __init te12xp_init(void) +{ + int res; + + res = zap_pci_module(&te12xp_driver); + + return res ? -ENODEV : 0; +} + + +static void __exit te12xp_cleanup(void) +{ + pci_unregister_driver(&te12xp_driver); +} + +#ifdef LINUX26 +module_param(debug, int, S_IRUGO | S_IWUSR); +module_param(loopback, int, S_IRUGO | S_IWUSR); +module_param(t1e1override, int, S_IRUGO | S_IWUSR); +module_param(j1mode, int, S_IRUGO | S_IWUSR); +module_param(alarmdebounce, int, S_IRUGO | S_IWUSR); +#ifdef VPM_SUPPORT +module_param(vpmsupport, int, S_IRUGO | S_IWUSR); +module_param(vpmdtmfsupport, int, S_IRUGO | S_IWUSR); +module_param(vpmtsisupport, int, S_IRUGO | S_IWUSR); +#endif +#else +MODULE_PARM(debug, "i"); +MODULE_PARM(loopback, "i"); +MODULE_PARM(t1e1override, "i"); +MODULE_PARM(j1mode, "i"); +MODULE_PARM(alarmdebounce, "i"); +#ifdef VPM_SUPPORT +MODULE_PARM(vpmsupport, "i"); +MODULE_PARM(vpmdtmfsupport, "i"); +MODULE_PARM(vpmtsisupport, "i"); +MODULE_PARM(vpmnlptype, "i"); +MODULE_PARM(vpmnlpthresh, "i"); +MODULE_PARM(vpmnlpmaxsupp, "i"); +#endif +#endif + +#ifdef MODULE_LICENSE +MODULE_LICENSE("GPL"); +#endif + +module_init(te12xp_init); +module_exit(te12xp_cleanup); diff -uNr zaptel-1.4.8/wcte12xp/.svn/text-base/GpakApi.c.svn-base zaptel-1.4/wcte12xp/.svn/text-base/GpakApi.c.svn-base --- zaptel-1.4.8/wcte12xp/.svn/text-base/GpakApi.c.svn-base 1970-01-01 01:00:00.000000000 +0100 +++ zaptel-1.4/wcte12xp/.svn/text-base/GpakApi.c.svn-base 2008-02-03 17:46:02.000000000 +0100 @@ -0,0 +1,1613 @@ +/* + * Copyright (c) 2005, Adaptive Digital Technologies, Inc. + * + * File Name: GpakApi.c + * + * Description: + * This file contains user API functions to communicate with DSPs executing + * G.PAK software. The file is integrated into the host processor connected + * to C55X G.PAK DSPs via a Host Port Interface. + * + * Version: 1.0 + * + * Revision History: + * 06/15/05 - Initial release. + * 11/15/2006 - 24 TDM-TDM Channels EC release + * + * This program has been released under the terms of the GPL version 2 by + * permission of Adaptive Digital Technologies, Inc. The standard + * GPL disclaimer is given inline below for your convenience. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include "zaptel.h" + +#include "GpakHpi.h" +#include "vpmadt032.h" +#include "GpakApi.h" +#include "gpakenum.h" + +#ifdef VPM_SUPPORT + +/* DSP to Host interface block offsets. */ +#define REPLY_MSG_PNTR_OFFSET 0 /* I/F blk offset to Reply Msg Pointer */ +#define CMD_MSG_PNTR_OFFSET 2 /* I/F blk offset to Command Msg Pointer */ +#define EVENT_MSG_PNTR_OFFSET 4 /* I/F blk offset to Event Msg Pointer */ +#define PKT_BUFR_MEM_OFFSET 6 /* I/F blk offset to Packet Buffer memory */ +#define DSP_STATUS_OFFSET 8 /* I/F blk offset to DSP Status */ +#define VERSION_ID_OFFSET 9 /* I/F blk offset to G.PAK Version Id */ +#define MAX_CMD_MSG_LEN_OFFSET 10 /* I/F blk offset to Max Cmd Msg Length */ +#define CMD_MSG_LEN_OFFSET 11 /* I/F blk offset to Command Msg Length */ +#define REPLY_MSG_LEN_OFFSET 12 /* I/F blk offset to Reply Msg Length */ +#define NUM_CHANNELS_OFFSET 13 /* I/F blk offset to Num Built Channels */ +#define NUM_PKT_CHANNELS_OFFSET 14 /* I/F blk offset to Num Pkt Channels */ +#define NUM_CONFERENCES_OFFSET 15 /* I/F blk offset to Num Conferences */ +//#define CPU_USAGE_OFFSET_1MS 16 /* I/F blk offset to CPU Usage statistics */ +#define CPU_USAGE_OFFSET 18 /* I/F blk offset to CPU Usage statistics */ +//#define CPU_USAGE_OFFSET_10MS 20 /* I/F blk offset to CPU Usage statistics */ +#define FRAMING_STATS_OFFSET 22 /* I/F blk offset to Framing statistics */ + +//#define GPAK_RELEASE_Rate rate10ms +// = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = +// Macro to reconstruct a 32-bit value from two 16-bit values. +// Parameter p32: 32-bit-wide destination +// Parameter p16: 16-bit-wide source array of length 2 words +#define RECONSTRUCT_LONGWORD(p32, p16) p32 = (DSP_ADDRESS)p16[0]<<16; \ + p32 |= (unsigned long)p16[1] +// = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = + +/* DSP Status value definitions. */ +#define DSP_INIT_STATUS 0x5555 /* DSP Initialized status value */ +#define HOST_INIT_STATUS 0xAAAA /* Host Initialized status value */ + +/* Circular packet buffer information structure offsets. */ +#define CB_BUFR_BASE 0 /* pointer to base of circular buffer */ +#define CB_BUFR_SIZE 2 /* size of buffer (words) */ +#define CB_BUFR_PUT_INDEX 3 /* offset in buffer for next write */ +#define CB_BUFR_TAKE_INDEX 4 /* offset in buffer for next read */ +#define CIRC_BUFFER_INFO_STRUCT_SIZE 6 + +/* Miscellaneous definitions. */ +#define MSG_BUFFER_SIZE 100 /* size (words) of Host msg buffer */ +#define WORD_BUFFER_SIZE 84 /* size of DSP Word buffer (words) */ + +#ifdef __TMS320C55XX__ // debug sections if not on host +#pragma DATA_SECTION(pDspIfBlk,"GPAKAPIDEBUG_SECT") +#pragma DATA_SECTION(MaxCmdMsgLen,"GPAKAPIDEBUG_SECT") +#pragma DATA_SECTION(MaxChannels,"GPAKAPIDEBUG_SECT") +#pragma DATA_SECTION(DlByteBufr,"GPAKAPIDEBUG_SECT") +#pragma DATA_SECTION(DlWordBufr,"GPAKAPIDEBUG_SECT") +#pragma DATA_SECTION(pEventFifoAddress,"GPAKAPIDEBUG_SECT") +#endif + +/* Host variables related to Host to DSP interface. */ +static DSP_ADDRESS pDspIfBlk[MAX_DSP_CORES]; /* DSP address of I/F block */ +static DSP_WORD MaxCmdMsgLen[MAX_DSP_CORES]; /* max Cmd msg length (octets) */ +static unsigned short int MaxChannels[MAX_DSP_CORES]; /* max num channels */ + +//static unsigned short int MaxPktChannels[MAX_DSP_CORES]; /* max num pkt channels */ +//static unsigned short int MaxConfs[MAX_DSP_CORES]; /* max num conferences */ +//static DSP_ADDRESS pPktInBufr[MAX_DSP_CORES][MAX_PKT_CHANNELS]; /* Pkt In buffer */ +//static DSP_ADDRESS pPktOutBufr[MAX_DSP_CORES][MAX_PKT_CHANNELS]; /* Pkt Out buffer */ +static DSP_ADDRESS pEventFifoAddress[MAX_DSP_CORES]; /* event fifo */ + +static unsigned char DlByteBufr[DOWNLOAD_BLOCK_SIZE * 2]; /* Dowload byte buf */ +static DSP_WORD DlWordBufr[DOWNLOAD_BLOCK_SIZE]; /* Dowload word buffer */ + + +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + * CheckDspReset - Check if the DSP was reset. + * + * FUNCTION + * This function determines if the DSP was reset and is ready. If reset + * occurred, it reads interface parameters and calculates DSP addresses. + * + * RETURNS + * -1 = DSP is not ready. + * 0 = Reset did not occur. + * 1 = Reset occurred. + * + */ +static int CheckDspReset( + int DspId /* DSP Identifier (0 to MaxDSPCores-1) */ + ) +{ + DSP_ADDRESS IfBlockPntr; /* Interface Block pointer */ + DSP_WORD DspStatus; /* DSP Status */ + DSP_WORD DspChannels; /* number of DSP channels */ + //DSP_WORD DspConfs; /* number of DSP conferences */ + //DSP_ADDRESS PktBufrMem; /* address of Packet Buffer */ + DSP_WORD Temp[2]; + //unsigned short int i; /* loop index / counter */ + + /* Read the pointer to the Interface Block. */ + gpakReadDspMemory(DspId, DSP_IFBLK_ADDRESS, 2, Temp); + RECONSTRUCT_LONGWORD(IfBlockPntr, Temp); + + /* If the pointer is zero, return with an indication the DSP is not + ready. */ + if (IfBlockPntr == 0) + return (-1); + + /* Read the DSP's Status. */ + gpakReadDspMemory(DspId, IfBlockPntr + DSP_STATUS_OFFSET, 1, &DspStatus); + + /* If status indicates the DSP was reset, read the DSP's interface + parameters and calculate DSP addresses. */ + if (DspStatus == DSP_INIT_STATUS || + ((DspStatus == HOST_INIT_STATUS) && (pDspIfBlk[DspId] == 0))) + { + /* Save the address of the DSP's Interface Block. */ + pDspIfBlk[DspId] = IfBlockPntr; + + /* Read the DSP's interface parameters. */ + gpakReadDspMemory(DspId, IfBlockPntr + MAX_CMD_MSG_LEN_OFFSET, 1, + &(MaxCmdMsgLen[DspId])); + + /* read the number of configured DSP channels */ + gpakReadDspMemory(DspId, IfBlockPntr + NUM_CHANNELS_OFFSET, 1, + &DspChannels); + if (DspChannels > MAX_CHANNELS) + MaxChannels[DspId] = MAX_CHANNELS; + else + MaxChannels[DspId] = (unsigned short int) DspChannels; +#if 0 + /* read the number of configured DSP conferences */ + gpakReadDspMemory(DspId, IfBlockPntr + NUM_CONFERENCES_OFFSET, 1, + &DspConfs); + if (DspConfs > MAX_CONFS) + MaxConfs[DspId] = MAX_CONFS; + else + MaxConfs[DspId] = (unsigned short int) DspConfs; + + + /* read the number of configured DSP packet channels */ + gpakReadDspMemory(DspId, IfBlockPntr + NUM_PKT_CHANNELS_OFFSET, 1, + &DspChannels); + if (DspChannels > MAX_PKT_CHANNELS) + MaxPktChannels[DspId] = MAX_PKT_CHANNELS; + else + MaxPktChannels[DspId] = (unsigned short int) DspChannels; + + + /* read the pointer to the circular buffer infor struct table */ + gpakReadDspMemory(DspId, IfBlockPntr + PKT_BUFR_MEM_OFFSET, 2, Temp); + RECONSTRUCT_LONGWORD(PktBufrMem, Temp); + + + /* Determine the addresses of each channel's Packet buffers. */ + for (i = 0; i < MaxPktChannels[DspId]; i++) + { + pPktInBufr[DspId][i] = PktBufrMem; + pPktOutBufr[DspId][i] = PktBufrMem + CIRC_BUFFER_INFO_STRUCT_SIZE; + PktBufrMem += (CIRC_BUFFER_INFO_STRUCT_SIZE*2); + } +#endif + + /* read the pointer to the event fifo info struct */ + gpakReadDspMemory(DspId, IfBlockPntr + EVENT_MSG_PNTR_OFFSET, 2, Temp); + RECONSTRUCT_LONGWORD(pEventFifoAddress[DspId], Temp); + + /* Set the DSP Status to indicate the host recognized the reset. */ + DspStatus = HOST_INIT_STATUS; + gpakWriteDspMemory(DspId, IfBlockPntr + DSP_STATUS_OFFSET, 1, + &DspStatus); + + /* Return with an indication that a reset occurred. */ + return (1); + } + + /* If status doesn't indicate the host recognized a reset, return with an + indication the DSP is not ready. */ + if ((DspStatus != HOST_INIT_STATUS) || (pDspIfBlk[DspId] == 0)) + return (-1); + + /* Return with an indication that a reset did not occur. */ + return (0); +} + + +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + * WriteDspCmdMessage - Write a Host Command/Request message to DSP. + * + * FUNCTION + * This function writes a Host Command/Request message into DSP memory and + * informs the DSP of the presence of the message. + * + * RETURNS + * -1 = Unable to write message (msg len or DSP Id invalid or DSP not ready) + * 0 = Temporarily unable to write message (previous Cmd Msg busy) + * 1 = Message written successfully + * + */ +static int WriteDspCmdMessage( + int DspId, /* DSP Identifier (0 to MaxDSPCores-1) */ + DSP_WORD *pMessage, /* pointer to Command message */ + DSP_WORD MsgLength /* length of message (octets) */ + ) +{ + DSP_WORD CmdMsgLength; /* current Cmd message length */ + DSP_WORD Temp[2]; + DSP_ADDRESS BufferPointer; /* message buffer pointer */ + + /* Check if the DSP was reset and is ready. */ + if (CheckDspReset(DspId) == -1) + return (-1); + + /* Make sure the message length is valid. */ + if ((MsgLength < 1) || (MsgLength > MaxCmdMsgLen[DspId])) + return (-1); + + /* Make sure a previous Command message is not in use by the DSP. */ + gpakReadDspMemory(DspId, pDspIfBlk[DspId] + CMD_MSG_LEN_OFFSET, 1, + &CmdMsgLength); + if (CmdMsgLength != 0) + return (0); + + /* Purge any previous Reply message that wasn't read. */ + gpakWriteDspMemory(DspId, pDspIfBlk[DspId] + REPLY_MSG_LEN_OFFSET, 1, + &CmdMsgLength); + + /* Copy the Command message into DSP memory. */ + gpakReadDspMemory(DspId, pDspIfBlk[DspId] + CMD_MSG_PNTR_OFFSET, 2, Temp); + RECONSTRUCT_LONGWORD(BufferPointer, Temp); + gpakWriteDspMemory(DspId, BufferPointer, (MsgLength + 1) / 2, pMessage); + + /* Store the message length in DSP's Command message length (flags DSP that + a Command message is ready). */ + CmdMsgLength = MsgLength; + gpakWriteDspMemory(DspId, pDspIfBlk[DspId] + CMD_MSG_LEN_OFFSET, 1, + &CmdMsgLength); + + /* Return with an indication the message was written. */ + return (1); +} + + +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + * ReadDspReplyMessage - Read a DSP Reply message from DSP. + * + * FUNCTION + * This function reads a DSP Reply message from DSP memory. + * + * RETURNS + * -1 = Unable to write message (msg len or DSP Id invalid or DSP not ready) + * 0 = No message available (DSP Reply message empty) + * 1 = Message read successfully (message and length stored in variables) + * + */ +static int ReadDspReplyMessage( + int DspId, /* DSP Identifier (0 to MaxDSPCores-1) */ + DSP_WORD *pMessage, /* pointer to Reply message buffer */ + DSP_WORD *pMsgLength /* pointer to msg length var (octets) */ + ) +{ + DSP_WORD MsgLength; /* message length */ + DSP_ADDRESS BufferPointer; /* message buffer pointer */ + DSP_WORD Temp[2]; + + /* Check if the DSP was reset and is ready. */ + if (CheckDspReset(DspId) == -1) + return (-1); + + /* Check if a Reply message is ready. */ + gpakReadDspMemory(DspId, pDspIfBlk[DspId] + REPLY_MSG_LEN_OFFSET, 1, + &MsgLength); + if (MsgLength == 0) + return (0); + + /* Make sure the message length is valid. */ + if (MsgLength > *pMsgLength) + return (-1); + + /* Copy the Reply message from DSP memory. */ + gpakReadDspMemory(DspId, pDspIfBlk[DspId] + REPLY_MSG_PNTR_OFFSET, 2, Temp); + RECONSTRUCT_LONGWORD(BufferPointer, Temp); + gpakReadDspMemory(DspId, BufferPointer, (MsgLength + 1) / 2, pMessage); + + /* Store the message length in the message length variable. */ + *pMsgLength = MsgLength; + + /* Indicate a Reply message is not ready. */ + MsgLength = 0; + gpakWriteDspMemory(DspId, pDspIfBlk[DspId] + REPLY_MSG_LEN_OFFSET, 1, + &MsgLength); + + /* Return with an indication the message was read. */ + return (1); +} + +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + * ReadCircBuffer - Read from a DSP circular buffer. + * + * FUNCTION + * This function reads a block of words from a DSP circular buffer. The Take + * address is incremented by the number of words read adjusting for buffer + * wrap. + * + * RETURNS + * nothing + * + */ +static void ReadCircBuffer( + int DspId, /* DSP Identifier (0 to MaxDSPCores-1) */ + DSP_ADDRESS BufrBaseAddress, /* address of base of circular buffer */ + DSP_ADDRESS BufrLastAddress, /* address of last word in buffer */ + DSP_ADDRESS *TakeAddress, /* pointer to address in buffer for read */ + DSP_WORD *pWordBuffer, /* pointer to buffer for words read */ + DSP_WORD NumWords /* number of words to read */ + ) +{ + DSP_WORD WordsTillEnd; /* number of words until end of buffer */ + + /* Determine the number of words from the start address until the end of the + buffer. */ + WordsTillEnd = BufrLastAddress - *TakeAddress + 1; + + /* If a buffer wrap will occur, read the first part at the end of the + buffer followed by the second part at the beginning of the buffer. */ + if (NumWords > WordsTillEnd) + { + gpakReadDspMemory(DspId, *TakeAddress, WordsTillEnd, pWordBuffer); + gpakReadDspMemory(DspId, BufrBaseAddress, NumWords - WordsTillEnd, + &(pWordBuffer[WordsTillEnd])); + *TakeAddress = BufrBaseAddress + NumWords - WordsTillEnd; + } + + /* If a buffer wrap will not occur, read all words starting at the current + take address in the buffer. */ + else + { + gpakReadDspMemory(DspId, *TakeAddress, NumWords, pWordBuffer); + if (NumWords == WordsTillEnd) + *TakeAddress = BufrBaseAddress; + else + *TakeAddress = *TakeAddress + NumWords; + } + return; +} + + +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + * VerifyReply - Verify the reply message is correct for the command sent. + * + * FUNCTION + * This function verifies correct reply message content for the command that + * was just sent. + * + * RETURNS + * 0 = Incorrect + * 1 = Correct + * + */ +static int VerifyReply( + DSP_WORD *pMsgBufr, /* pointer to Reply message buffer */ + int CheckType, /* reply check type */ + DSP_WORD CheckValue /* reply check value */ + ) +{ + + /* Verify Channel or Conference Id. */ + if (CheckType == 1) + { + if (((pMsgBufr[1] >> 8) & 0xFF) != CheckValue) + return (0); + } + + /* Verify Test Mode Id. */ + else if (CheckType == 2) + { + if (pMsgBufr[1] != CheckValue) + return (0); + } + + /* Return with an indication of correct reply. */ + return (1); +} + + +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + * TransactCmd - Send a command to the DSP and receive it's reply. + * + * FUNCTION + * This function sends the specified command to the DSP and receives the DSP's + * reply. + * + * RETURNS + * Length of reply message (0 = Failure) + * + */ +static unsigned int TransactCmd( + int DspId, /* DSP Identifier (0 to MaxDSPCores-1) */ + DSP_WORD *pMsgBufr, /* pointer to Cmd/Reply message buffer */ + DSP_WORD CmdLength, /* length of command message (octets) */ + DSP_WORD ReplyType, /* required type of reply message */ + DSP_WORD ReplyLength, /* required length of reply message (octets) */ + int ReplyCheckType, /* reply check type */ + DSP_WORD ReplyCheckValue /* reply check value */ + ) +{ + int FuncStatus; /* function status */ + int LoopCount; /* wait loop counter */ + DSP_WORD RcvReplyLength; /* received Reply message length */ + DSP_WORD RcvReplyType; /* received Reply message type code */ + DSP_WORD RetValue; /* return value */ + + /* Default the return value to indicate a failure. */ + RetValue = 0; + + /* Lock access to the DSP. */ + gpakLockAccess(DspId); + + /* Attempt to write the command message to the DSP. */ + LoopCount = 0; + while ((FuncStatus = WriteDspCmdMessage(DspId, pMsgBufr, CmdLength)) != 1) + { + if (FuncStatus == -1) + break; + if (++LoopCount > MAX_WAIT_LOOPS) + break; + gpakHostDelay(); + } + + /* Attempt to read the reply message from the DSP if the command message was + sent successfully. */ + if (FuncStatus == 1) + { + for (LoopCount = 0; LoopCount < MAX_WAIT_LOOPS; LoopCount++) + { + RcvReplyLength = MSG_BUFFER_SIZE * 2; + FuncStatus = ReadDspReplyMessage(DspId, pMsgBufr, &RcvReplyLength); + if (FuncStatus == 1) + { + RcvReplyType = (pMsgBufr[0] >> 8) & 0xFF; + if ((RcvReplyLength >= ReplyLength) && + (RcvReplyType == ReplyType) && + VerifyReply(pMsgBufr, ReplyCheckType, ReplyCheckValue)) + { + RetValue = RcvReplyLength; + break; + } + else if (RcvReplyType == MSG_NULL_REPLY) + break; + } + else if (FuncStatus == -1) + break; + gpakHostDelay(); + } + } + + /* Unlock access to the DSP. */ + gpakUnlockAccess(DspId); + + /* Return the length of the reply message (0 = failure). */ + return (RetValue); +} + +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + * gpakConfigurePorts - Configure a DSP's serial ports. + * + * FUNCTION + * This function configures a DSP's serial ports. + * + * RETURNS + * Status code indicating success or a specific error. + * + */ +gpakConfigPortStatus_t gpakConfigurePorts( + unsigned short int DspId, /* DSP Id (0 to MaxDSPCores-1) */ + GpakPortConfig_t *pPortConfig, /* pointer to Port Config info */ + GPAK_PortConfigStat_t *pStatus /* pointer to Port Config Status */ + ) +{ + DSP_WORD MsgBuffer[MSG_BUFFER_SIZE]; /* message buffer */ + + /* Make sure the DSP Id is valid. */ + if (DspId >= MAX_DSP_CORES) + return (CpsInvalidDsp); + + /* Build the Configure Serial Ports message. */ + MsgBuffer[0] = MSG_CONFIGURE_PORTS << 8; + MsgBuffer[1] = (DSP_WORD) + ((pPortConfig->SlotsSelect1 << 12) | + ((pPortConfig->FirstBlockNum1 << 8) & 0x0F00) | + ((pPortConfig->SecBlockNum1 << 4) & 0x00F0)); + MsgBuffer[2] = (DSP_WORD) pPortConfig->FirstSlotMask1; + MsgBuffer[3] = (DSP_WORD) pPortConfig->SecSlotMask1; + MsgBuffer[4] = (DSP_WORD) + ((pPortConfig->SlotsSelect2 << 12) | + ((pPortConfig->FirstBlockNum2 << 8) & 0x0F00) | + ((pPortConfig->SecBlockNum2 << 4) & 0x00F0)); + MsgBuffer[5] = (DSP_WORD) pPortConfig->FirstSlotMask2; + MsgBuffer[6] = (DSP_WORD) pPortConfig->SecSlotMask2; + MsgBuffer[7] = (DSP_WORD) + ((pPortConfig->SlotsSelect3 << 12) | + ((pPortConfig->FirstBlockNum3 << 8) & 0x0F00) | + ((pPortConfig->SecBlockNum3 << 4) & 0x00F0)); + MsgBuffer[8] = (DSP_WORD) pPortConfig->FirstSlotMask3; + MsgBuffer[9] = (DSP_WORD) pPortConfig->SecSlotMask3; + + MsgBuffer[10] = (DSP_WORD) + (((pPortConfig->DxDelay1 << 11) & 0x0800) | + ((pPortConfig->RxDataDelay1 << 9) & 0x0600) | + ((pPortConfig->TxDataDelay1 << 7) & 0x0180) | + ((pPortConfig->RxClockPolarity1 << 6) & 0x0040) | + ((pPortConfig->TxClockPolarity1 << 5) & 0x0020) | + ((pPortConfig->RxFrameSyncPolarity1 << 4) & 0x0010) | + ((pPortConfig->TxFrameSyncPolarity1 << 3) & 0x0008) | + ((pPortConfig->CompandingMode1 << 1) & 0x0006) | + (pPortConfig->SerialWordSize1 & 0x0001)); + + MsgBuffer[11] = (DSP_WORD) + (((pPortConfig->DxDelay2 << 11) & 0x0800) | + ((pPortConfig->RxDataDelay2 << 9) & 0x0600) | + ((pPortConfig->TxDataDelay2 << 7) & 0x0180) | + ((pPortConfig->RxClockPolarity2 << 6) & 0x0040) | + ((pPortConfig->TxClockPolarity2 << 5) & 0x0020) | + ((pPortConfig->RxFrameSyncPolarity2 << 4) & 0x0010) | + ((pPortConfig->TxFrameSyncPolarity2 << 3) & 0x0008) | + ((pPortConfig->CompandingMode2 << 1) & 0x0006) | + (pPortConfig->SerialWordSize1 & 0x0001)); + + MsgBuffer[12] = (DSP_WORD) + (((pPortConfig->DxDelay3 << 11) & 0x0800) | + ((pPortConfig->RxDataDelay3 << 9) & 0x0600) | + ((pPortConfig->TxDataDelay3 << 7) & 0x0180) | + ((pPortConfig->RxClockPolarity3 << 6) & 0x0040) | + ((pPortConfig->TxClockPolarity3 << 5) & 0x0020) | + ((pPortConfig->RxFrameSyncPolarity3 << 4) & 0x0010) | + ((pPortConfig->TxFrameSyncPolarity3 << 3) & 0x0008) | + ((pPortConfig->CompandingMode3 << 1) & 0x0006) | + (pPortConfig->SerialWordSize3 & 0x0001)); + + MsgBuffer[13] = (DSP_WORD) pPortConfig->ThirdSlotMask1; + MsgBuffer[14] = (DSP_WORD) pPortConfig->FouthSlotMask1; + MsgBuffer[15] = (DSP_WORD) pPortConfig->FifthSlotMask1; + MsgBuffer[16] = (DSP_WORD) pPortConfig->SixthSlotMask1; + MsgBuffer[17] = (DSP_WORD) pPortConfig->SevenSlotMask1; + MsgBuffer[18] = (DSP_WORD) pPortConfig->EightSlotMask1; + + MsgBuffer[19] = (DSP_WORD) pPortConfig->ThirdSlotMask2;; + MsgBuffer[20] = (DSP_WORD) pPortConfig->FouthSlotMask2; + MsgBuffer[21] = (DSP_WORD) pPortConfig->FifthSlotMask2;; + MsgBuffer[22] = (DSP_WORD) pPortConfig->SixthSlotMask2; + MsgBuffer[23] = (DSP_WORD) pPortConfig->SevenSlotMask2;; + MsgBuffer[24] = (DSP_WORD) pPortConfig->EightSlotMask2; + + MsgBuffer[25] = (DSP_WORD) pPortConfig->ThirdSlotMask3;; + MsgBuffer[26] = (DSP_WORD) pPortConfig->FouthSlotMask3; + MsgBuffer[27] = (DSP_WORD) pPortConfig->FifthSlotMask3;; + MsgBuffer[28] = (DSP_WORD) pPortConfig->SixthSlotMask3; + MsgBuffer[29] = (DSP_WORD) pPortConfig->SevenSlotMask3;; + MsgBuffer[30] = (DSP_WORD) pPortConfig->EightSlotMask3; + + + /* Attempt to send the Configure Serial Ports message to the DSP and receive + it's reply. */ + if (!TransactCmd(DspId, MsgBuffer, 62, MSG_CONFIG_PORTS_REPLY, 4, 0, 0)) + return (CpsDspCommFailure); + + /* Return with an indication of success or failure based on the return + status in the reply message. */ + *pStatus = (GPAK_PortConfigStat_t) (MsgBuffer[1] & 0xFF); + if (*pStatus == Pc_Success) + return (CpsSuccess); + else + return (CpsParmError); +} + + +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + * gpakConfigureChannel - Configure a DSP's Channel. + * + * FUNCTION + * This function configures a DSP's Channel. + * + * RETURNS + * Status code indicating success or a specific error. + * + */ +gpakConfigChanStatus_t gpakConfigureChannel( + unsigned short int DspId, /* DSP Id (0 to MaxDSPCores-1) */ + unsigned short int ChannelId, /* Channel Id (0 to MaxChannels-1) */ + GpakChanType ChannelType, /* Channel Type */ + GpakChannelConfig_t *pChanConfig, /* pointer to Channel Config info */ + GPAK_ChannelConfigStat_t *pStatus /* pointer to Channel Config Status */ + ) +{ + DSP_WORD MsgBuffer[MSG_BUFFER_SIZE]; /* message buffer */ + DSP_WORD MsgLength; /* message length */ + + /* Make sure the DSP Id is valid. */ + if (DspId >= MAX_DSP_CORES) + return (CcsInvalidDsp); + + /* Make sure the Channel Id is valid. */ + if (ChannelId >= MaxChannels[DspId]) + return (CcsInvalidChannel); + + /* Build the Configure Channel message based on the Channel Type. */ + switch (ChannelType) + { + + /* PCM to Packet channel type. */ + case tdmToTdm: + + MsgBuffer[2] = (DSP_WORD) + ((pChanConfig->PcmInPortA << 8) | + (pChanConfig->PcmInSlotA & 0xFF)); + MsgBuffer[3] = (DSP_WORD) + ((pChanConfig->PcmOutPortA << 8) | + (pChanConfig->PcmOutSlotA & 0xFF)); + + MsgBuffer[4] = (DSP_WORD) + ((pChanConfig->PcmInPortB << 8) | + (pChanConfig->PcmInSlotB & 0xFF)); + MsgBuffer[5] = (DSP_WORD) + ((pChanConfig->PcmOutPortB << 8) | + (pChanConfig->PcmOutSlotB & 0xFF)); + + MsgBuffer[6] = (DSP_WORD) + ( + ((pChanConfig->FaxCngDetB <<11) & 0x0800) | + ((pChanConfig->FaxCngDetA <<10) & 0x0400) | + ((pChanConfig->MuteToneB << 9) & 0x0200) | + ((pChanConfig->MuteToneA << 8) & 0x0100) | + ((pChanConfig->FrameRate << 6) & 0x00C0) | + ((pChanConfig->ToneTypesB << 5) & 0x0020) | + ((pChanConfig->ToneTypesA << 4) & 0x0010) | + ((pChanConfig->SoftwareCompand & 3) << 2) | + (pChanConfig->EcanEnableB << 1) | + (pChanConfig->EcanEnableA & 1) + ); + + MsgBuffer[7] = (DSP_WORD) + pChanConfig->EcanParametersA.EcanTapLength; + MsgBuffer[8] = (DSP_WORD) + pChanConfig->EcanParametersA.EcanNlpType; + MsgBuffer[9] = (DSP_WORD) + pChanConfig->EcanParametersA.EcanAdaptEnable; + MsgBuffer[10] = (DSP_WORD) + pChanConfig->EcanParametersA.EcanG165DetEnable; + MsgBuffer[11] = (DSP_WORD) + pChanConfig->EcanParametersA.EcanDblTalkThresh; + MsgBuffer[12] = (DSP_WORD) + pChanConfig->EcanParametersA.EcanNlpThreshold; + MsgBuffer[13] = (DSP_WORD) + pChanConfig->EcanParametersA.EcanNlpConv; + MsgBuffer[14] = (DSP_WORD) + pChanConfig->EcanParametersA.EcanNlpUnConv; + MsgBuffer[15] = (DSP_WORD) + pChanConfig->EcanParametersA.EcanNlpMaxSuppress; + + MsgBuffer[16] = (DSP_WORD) + pChanConfig->EcanParametersA.EcanCngThreshold; + MsgBuffer[17] = (DSP_WORD) + pChanConfig->EcanParametersA.EcanAdaptLimit; + MsgBuffer[18] = (DSP_WORD) + pChanConfig->EcanParametersA.EcanCrossCorrLimit; + MsgBuffer[19] = (DSP_WORD) + pChanConfig->EcanParametersA.EcanNumFirSegments; + MsgBuffer[20] = (DSP_WORD) + pChanConfig->EcanParametersA.EcanFirSegmentLen; + + MsgBuffer[21] = (DSP_WORD) + pChanConfig->EcanParametersB.EcanTapLength; + MsgBuffer[22] = (DSP_WORD) + pChanConfig->EcanParametersB.EcanNlpType; + MsgBuffer[23] = (DSP_WORD) + pChanConfig->EcanParametersB.EcanAdaptEnable; + MsgBuffer[24] = (DSP_WORD) + pChanConfig->EcanParametersB.EcanG165DetEnable; + MsgBuffer[25] = (DSP_WORD) + pChanConfig->EcanParametersB.EcanDblTalkThresh; + MsgBuffer[26] = (DSP_WORD) + pChanConfig->EcanParametersB.EcanNlpThreshold; + MsgBuffer[27] = (DSP_WORD) + pChanConfig->EcanParametersB.EcanNlpConv; + MsgBuffer[28] = (DSP_WORD) + pChanConfig->EcanParametersB.EcanNlpUnConv; + MsgBuffer[29] = (DSP_WORD) + pChanConfig->EcanParametersB.EcanNlpMaxSuppress; + MsgBuffer[30] = (DSP_WORD) + pChanConfig->EcanParametersB.EcanCngThreshold; + MsgBuffer[31] = (DSP_WORD) + pChanConfig->EcanParametersB.EcanAdaptLimit; + MsgBuffer[32] = (DSP_WORD) + pChanConfig->EcanParametersB.EcanCrossCorrLimit; + MsgBuffer[33] = (DSP_WORD) + pChanConfig->EcanParametersB.EcanNumFirSegments; + MsgBuffer[34] = (DSP_WORD) + pChanConfig->EcanParametersB.EcanFirSegmentLen; + + MsgLength = 70; // byte number == 35*2 + break; + + + /* Unknown (invalid) channel type. */ + default: + *pStatus = Cc_InvalidChannelType; + return (CcsParmError); + } + + MsgBuffer[0] = MSG_CONFIGURE_CHANNEL << 8; + MsgBuffer[1] = (DSP_WORD) ((ChannelId << 8) | (ChannelType & 0xFF)); + + /* Attempt to send the Configure Channel message to the DSP and receive it's + reply. */ + if (!TransactCmd(DspId, MsgBuffer, MsgLength, MSG_CONFIG_CHAN_REPLY, 4, 1, + (DSP_WORD) ChannelId)) + return (CcsDspCommFailure); + + /* Return with an indication of success or failure based on the return + status in the reply message. */ + *pStatus = (GPAK_ChannelConfigStat_t) (MsgBuffer[1] & 0xFF); + if (*pStatus == Cc_Success) + return (CcsSuccess); + else + return (CcsParmError); +} + +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + * gpakTearDownChannel - Tear Down a DSP's Channel. + * + * FUNCTION + * This function tears down a DSP's Channel. + * + * RETURNS + * Status code indicating success or a specific error. + * + */ +gpakTearDownStatus_t gpakTearDownChannel( + unsigned short int DspId, /* DSP Id (0 to MaxDSPCores-1) */ + unsigned short int ChannelId, /* Channel Id (0 to MaxChannels-1) */ + GPAK_TearDownChanStat_t *pStatus /* pointer to Tear Down Status */ + ) +{ + DSP_WORD MsgBuffer[MSG_BUFFER_SIZE]; /* message buffer */ + + /* Make sure the DSP Id is valid. */ + if (DspId >= MAX_DSP_CORES) + return (TdsInvalidDsp); + + /* Make sure the Channel Id is valid. */ + if (ChannelId >= MaxChannels[DspId]) + return (TdsInvalidChannel); + + /* Build the Tear Down Channel message. */ + MsgBuffer[0] = MSG_TEAR_DOWN_CHANNEL << 8; + MsgBuffer[1] = (DSP_WORD) (ChannelId << 8); + + /* Attempt to send the Tear Down Channel message to the DSP and receive it's + reply. */ + if (!TransactCmd(DspId, MsgBuffer, 3, MSG_TEAR_DOWN_REPLY, 4, 1, + (DSP_WORD) ChannelId)) + return (TdsDspCommFailure); + + /* Return with an indication of success or failure based on the return + status in the reply message. */ + *pStatus = (GPAK_TearDownChanStat_t) (MsgBuffer[1] & 0xFF); + if (*pStatus == Td_Success) + return (TdsSuccess); + else + return (TdsError); +} + +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + * gpakAlgControl - Control an Algorithm. + * + * FUNCTION + * This function controls an Algorithm + * + * RETURNS + * Status code indicating success or a specific error. + * + */ +gpakAlgControlStat_t gpakAlgControl( + unsigned short int DspId, // DSP identifier + unsigned short int ChannelId, // channel identifier + GpakAlgCtrl_t ControlCode, // algorithm control code + GPAK_AlgControlStat_t *pStatus // pointer to return status + ) +{ + DSP_WORD MsgBuffer[MSG_BUFFER_SIZE]; /* message buffer */ + + /* Make sure the DSP Id is valid. */ + if (DspId >= MAX_DSP_CORES) + return (AcInvalidDsp); + + /* Make sure the Channel Id is valid. */ + if (ChannelId >= MaxChannels[DspId]) + return (AcInvalidChannel); + + MsgBuffer[0] = MSG_ALG_CONTROL << 8; + MsgBuffer[1] = (DSP_WORD) ((ChannelId << 8) | (ControlCode & 0xFF)); + + /* Attempt to send the Tear Down Channel message to the DSP and receive it's + reply. */ + //need_reply_len; + if (!TransactCmd(DspId, MsgBuffer, 4, MSG_ALG_CONTROL_REPLY, 4, 1, + (DSP_WORD) ChannelId)) + return (AcDspCommFailure); + + /* Return with an indication of success or failure based on the return + status in the reply message. */ + *pStatus = (GPAK_AlgControlStat_t) (MsgBuffer[1] & 0xFF); + if (*pStatus == Ac_Success) + return (AcSuccess); + else + return (AcParmError); + +} + +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + * gpakReadEventFIFOMessage - read from the event fifo + * + * FUNCTION + * This function reads a single event from the event fifo if one is available + * + * RETURNS + * Status code indicating success or a specific error. + * + * Notes: This function should be called in a loop until the return status + * indicates that the fifo is empty. + * + * If the event code equals "EventLoopbackTeardownComplete", then the + * contents of *pChannelId hold the coderBlockId that was assigned to + * the loopback coder that was torn down. + */ +gpakReadEventFIFOMessageStat_t gpakReadEventFIFOMessage( + unsigned short int DspId, // DSP identifier + unsigned short int *pChannelId, // pointer to channel identifier + GpakAsyncEventCode_t *pEventCode, // pointer to Event Code + GpakAsyncEventData_t *pEventData // pointer to Event Data Struct + ) +{ + DSP_WORD WordBuffer[WORD_BUFFER_SIZE]; /* DSP words buffer */ + GpakAsyncEventCode_t EventCode; /* DSP's event code */ + DSP_WORD EventDataLength; /* Length of event to read */ + DSP_WORD ChannelId; /* DSP's channel Id */ + DSP_ADDRESS EventInfoAddress; /* address of EventFIFO info structure */ + DSP_ADDRESS BufrBaseAddress; /* base address of EventFIFO buffer */ + DSP_ADDRESS BufrLastAddress; /* last address of EventFIFO buffer */ + DSP_ADDRESS TakeAddress; /* current take address in fifo buffer */ + DSP_WORD BufrSize; /* size (in words) of event FIFO buffer */ + DSP_WORD PutIndex; /* event fifo put index */ + DSP_WORD TakeIndex; /* event fifo take index */ + DSP_WORD WordsReady; /* number words ready for read out of event fifo */ + DSP_WORD EventError; /* flag indicating error with event fifo msg */ + //DSP_WORD *pDebugData; /* debug data buffer pointer in event data struct */ + + /* Make sure the DSP Id is valid. */ + if (DspId >= MAX_DSP_CORES) + return (RefInvalidDsp); + + /* Lock access to the DSP. */ + gpakLockAccess(DspId); + + /* Check if the DSP was reset and is ready. */ + if (CheckDspReset(DspId) == -1) + { + gpakUnlockAccess(DspId); + return (RefDspCommFailure); + } + + /* Check if an event message is ready in the DSP. */ + EventInfoAddress = pEventFifoAddress[DspId]; + gpakReadDspMemory(DspId, EventInfoAddress, CIRC_BUFFER_INFO_STRUCT_SIZE, + WordBuffer); + RECONSTRUCT_LONGWORD(BufrBaseAddress, ((DSP_WORD *)&WordBuffer[CB_BUFR_BASE])); + BufrSize = WordBuffer[CB_BUFR_SIZE]; + PutIndex = WordBuffer[CB_BUFR_PUT_INDEX]; + TakeIndex = WordBuffer[CB_BUFR_TAKE_INDEX]; + if (PutIndex >= TakeIndex) + WordsReady = PutIndex - TakeIndex; + else + WordsReady = PutIndex + BufrSize - TakeIndex; + + if (WordsReady < 2) + { + gpakUnlockAccess(DspId); + return (RefNoEventAvail); + } + + /* Read the event header from the DSP's Event FIFO. */ + TakeAddress = BufrBaseAddress + TakeIndex; + BufrLastAddress = BufrBaseAddress + BufrSize - 1; + ReadCircBuffer(DspId, BufrBaseAddress, BufrLastAddress, &TakeAddress, + WordBuffer, 2); + TakeIndex += 2; + if (TakeIndex >= BufrSize) + TakeIndex -= BufrSize; + + ChannelId = (WordBuffer[0] >> 8) & 0xFF; + EventCode = (GpakAsyncEventCode_t)(WordBuffer[0] & 0xFF); + EventDataLength = WordBuffer[1]; + EventError = 0; + + switch (EventCode) + { + case EventToneDetect: + if (EventDataLength > WORD_BUFFER_SIZE) + { + gpakUnlockAccess(DspId); + return (RefInvalidEvent); + } + ReadCircBuffer(DspId, BufrBaseAddress, BufrLastAddress, &TakeAddress, + WordBuffer, EventDataLength); + pEventData->toneEvent.ToneCode = (GpakToneCodes_t) + (WordBuffer[0] & 0xFF); + pEventData->toneEvent.ToneDuration = WordBuffer[1]; + pEventData->toneEvent.Direction = WordBuffer[2]; + pEventData->toneEvent.DebugToneStatus = WordBuffer[3]; + TakeIndex += EventDataLength; + if (TakeIndex >= BufrSize) + TakeIndex -= BufrSize; + if (EventDataLength != 4) + EventError = 1; + break; + + default: + EventError = 1; + break; + }; + + /* Update the Take index in the DSP's Packet Out buffer information. */ + gpakWriteDspMemory(DspId, EventInfoAddress + CB_BUFR_TAKE_INDEX, 1, + &TakeIndex); + + /* Unlock access to the DSP. */ + gpakUnlockAccess(DspId); + + if (EventError) + return(RefInvalidEvent); + + *pChannelId = ChannelId; + *pEventCode = EventCode; + return(RefEventAvail); + +} + + +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + * gpakPingDsp - ping the DSP to see if it's alive + * + * FUNCTION + * This function checks if the DSP is still communicating with the host + * and returns the DSP SW version + * + * RETURNS + * Status code indicating success or a specific error. + */ +gpakPingDspStat_t gpakPingDsp( + unsigned short int DspId, // DSP identifier + unsigned short int *pDspSwVersion // DSP software version + ) +{ + DSP_WORD MsgBuffer[MSG_BUFFER_SIZE]; /* message buffer */ + DSP_WORD DspStatus; /* DSP's reply status */ + + /* Make sure the DSP Id is valid. */ + if (DspId >= MAX_DSP_CORES) + return (PngInvalidDsp); + + /* send value of 1, DSP increments it */ + MsgBuffer[0] = (MSG_PING << 8); + + /* Attempt to send the ping message to the DSP and receive it's + reply. */ + if (!TransactCmd(DspId, MsgBuffer, 1, MSG_PING_REPLY, 6, 0, 0)) + return (PngDspCommFailure); + + /* Return with an indication of success or failure based on the return + status in the reply message. */ + DspStatus = (MsgBuffer[1] & 0xFF); + if (DspStatus == 0) + { + *pDspSwVersion = MsgBuffer[2]; + return (PngSuccess); + } + else + return (PngDspCommFailure); +} + +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + * gpakSerialTxFixedValue - transmit a fixed value on a timeslot + * + * FUNCTION + * This function controls transmission of a fixed value out onto a serial + * port's timeslot. + * + * RETURNS + * Status code indicating success or a specific error. + */ +gpakSerialTxFixedValueStat_t gpakSerialTxFixedValue( + unsigned short int DspId, // DSP identifier + unsigned short int ChannelId, // channel identifier + GpakSerialPort_t PcmOutPort, // PCM Output Serial Port Id + unsigned short int PcmOutSlot, // PCM Output Time Slot + unsigned short int Value, // 16-bit value + GpakActivation State // activation state + ) +{ + DSP_WORD MsgBuffer[MSG_BUFFER_SIZE]; /* message buffer */ + DSP_WORD DspStatus; /* DSP's reply status */ + + /* Make sure the DSP Id is valid. */ + if (DspId >= MAX_DSP_CORES) + return (TfvInvalidDsp); + + /* Make sure the Channel Id is valid. */ + if (ChannelId >= MaxChannels[DspId]) + return (TfvInvalidChannel); + + + /* Build the message. */ + MsgBuffer[0] = MSG_SERIAL_TXVAL << 8; + MsgBuffer[1] = (DSP_WORD) ((ChannelId << 8) | (State & 0xFF)); + MsgBuffer[2] = (DSP_WORD) ((PcmOutPort << 8) | (PcmOutSlot & 0xFF)); + MsgBuffer[3] = (DSP_WORD) Value; + + /* Attempt to send the message to the DSP and receive it's + reply. */ + //need_reply_len; + if (!TransactCmd(DspId, MsgBuffer, 8, MSG_SERIAL_TXVAL_REPLY, 4, + 1, ChannelId)) + return (TfvDspCommFailure); + + /* Return with an indication of success or failure based on the return + status in the reply message. */ + DspStatus = (MsgBuffer[1] & 0xFF); + if (DspStatus == 0) + return (TfvSuccess); + else + return (TfvDspCommFailure); +} + +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + * gpakControlTdmLoopBack - control a serial port's loopback state + * + * FUNCTION + * This function enables/disables the tdm input to output looback mode on a + * serial port + * + * RETURNS + * Status code indicating success or a specific error. + */ + +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/ +gpakControlTdmLoopBackStat_t gpakControlTdmLoopBack( + unsigned short int DspId, // DSP identifier + GpakSerialPort_t SerialPort, // Serial Port Id + GpakActivation LoopBackState // Loopback State + ) +{ + DSP_WORD MsgBuffer[MSG_BUFFER_SIZE]; /* message buffer */ + DSP_WORD DspStatus; /* DSP's reply status */ + + /* Make sure the DSP Id is valid. */ + if (DspId >= MAX_DSP_CORES) + return (ClbInvalidDsp); + + /* Build the message. */ + MsgBuffer[0] = MSG_TDM_LOOPBACK << 8; + MsgBuffer[1] = (DSP_WORD) ((SerialPort << 8) | (LoopBackState & 0xFF)); + + /* Attempt to send the message to the DSP and receive it's + reply. */ + //need_reply_len; + if (!TransactCmd(DspId, MsgBuffer, 4, MSG_TDM_LOOPBACK_REPLY, 4, 0, 0)) + return (ClbDspCommFailure); + + /* Return with an indication of success or failure based on the return + status in the reply message. */ + DspStatus = (MsgBuffer[1] & 0xFF); + if (DspStatus == 0) + return (ClbSuccess); + else + return (ClbDspCommFailure); +} + +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + * gpakReadCpuUsage - Read CPU usage statistics from a DSP. + * + * FUNCTION + * This function reads the CPU usage statistics from a DSP's memory. The + * average CPU usage in units of .1 percent are obtained for each of the frame + * rates. + * + * RETURNS + * Status code indicating success or a specific error. + * + */ +gpakReadCpuUsageStat_t gpakReadCpuUsage( + unsigned short int DspId, // Dsp Identifier + unsigned short int *pPeakUsage, // pointer to peak usage variable + unsigned short int *pPrev1SecPeakUsage // peak usage over previous 1 second + ) +{ + DSP_WORD ReadBuffer[2]; /* DSP read buffer */ + + /* Make sure the DSP Id is valid. */ + if (DspId >= MAX_DSP_CORES) + return (RcuInvalidDsp); + + /* Lock access to the DSP. */ + gpakLockAccess(DspId); + + /* Check if the DSP was reset and is ready. */ + if (CheckDspReset(DspId) == -1) + return (RcuDspCommFailure); + + /* Read the CPU Usage statistics from the DSP. */ + gpakReadDspMemory(DspId, pDspIfBlk[DspId] + CPU_USAGE_OFFSET, 2, + ReadBuffer); + + /* Unlock access to the DSP. */ + gpakUnlockAccess(DspId); + + /* Store the usage statistics in the specified variables. */ + *pPrev1SecPeakUsage = ReadBuffer[0]; + *pPeakUsage = ReadBuffer[1]; + + /* Return with an indication the usage staistics were read successfully. */ + return (RcuSuccess); +} + +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + * gpakResetCpuUsageStats - reset the cpu usage statistics + * + * FUNCTION + * This function resets the cpu utilization statistics + * + * RETURNS + * Status code indicating success or a specific error. + */ +gpakResetCpuUsageStat_t gpakResetCpuUsageStats( + unsigned short int DspId // DSP identifier + ) +{ + DSP_WORD MsgBuffer[MSG_BUFFER_SIZE]; /* message buffer */ + DSP_WORD DspStatus; /* DSP's reply status */ + + /* Make sure the DSP Id is valid. */ + if (DspId >= MAX_DSP_CORES) + return (RstcInvalidDsp); + + MsgBuffer[0] = (MSG_RESET_USAGE_STATS << 8); + + /* Attempt to send the message to the DSP and receive it's reply. */ + //need_reply_len; + if (!TransactCmd(DspId, MsgBuffer, 2, MSG_RESET_USAGE_STATS_REPLY, 4, 0, 0)) + return (RstcDspCommFailure); + + /* Return with an indication of success or failure based on the return + status in the reply message. */ + DspStatus = (MsgBuffer[1] & 0xFF); + if (DspStatus == 0) + return (RstcSuccess); + else + return (RstcDspCommFailure); +} + +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + * gpakReadFramingStats + * + * FUNCTION + * This function reads a DSP's framing interrupt statistics + * + * RETURNS + * Status code indicating success or a specific error. + */ +gpakReadFramingStatsStatus_t gpakReadFramingStats( + unsigned short int DspId, // DSP identifier + unsigned short int *pFramingError1Count, // port 1 Framing error count + unsigned short int *pFramingError2Count, // port 2 Framing error count + unsigned short int *pFramingError3Count, // port 3 Framing error count + unsigned short int *pDmaStopErrorCount, // DMA-stoppage error count + unsigned short int *pDmaSlipStatsBuffer // DMA slips count + ) +{ + DSP_WORD ReadBuffer[10]; /* DSP read buffer */ + + /* Make sure the DSP Id is valid. */ + if (DspId >= MAX_DSP_CORES) + return (RfsInvalidDsp); + + /* Lock access to the DSP. */ + gpakLockAccess(DspId); + + /* Check if the DSP was reset and is ready. */ + if (CheckDspReset(DspId) == -1) + return (RfsDspCommFailure); + + /* Read the framing interrupt statistics from the DSP. */ + gpakReadDspMemory(DspId, pDspIfBlk[DspId] + FRAMING_STATS_OFFSET, 10, + ReadBuffer); + + /* Unlock access to the DSP. */ + gpakUnlockAccess(DspId); + + /* Store the framing statistics in the specified variables. */ + *pFramingError1Count = ReadBuffer[0]; + *pFramingError2Count = ReadBuffer[1]; + *pFramingError3Count = ReadBuffer[2]; + *pDmaStopErrorCount = ReadBuffer[3]; + + if(pDmaSlipStatsBuffer != 0) + // If users want to get the DMA slips count + { + pDmaSlipStatsBuffer[0] = ReadBuffer[4]; + pDmaSlipStatsBuffer[1] = ReadBuffer[5]; + pDmaSlipStatsBuffer[2] = ReadBuffer[6]; + pDmaSlipStatsBuffer[3] = ReadBuffer[7]; + pDmaSlipStatsBuffer[4] = ReadBuffer[8]; + pDmaSlipStatsBuffer[5] = ReadBuffer[9]; + + } + /* Return with an indication the statistics were read successfully. */ + return (RfsSuccess); +} + +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + * gpakResetFramingStats - reset a DSP's framing interrupt statistics + * + * FUNCTION + * This function resets a DSP's framing interrupt statistics + * + * RETURNS + * Status code indicating success or a specific error. + */ +gpakResetFramingStatsStatus_t gpakResetFramingStats( + unsigned short int DspId // DSP identifier + ) +{ + DSP_WORD MsgBuffer[MSG_BUFFER_SIZE]; /* message buffer */ + DSP_WORD DspStatus; /* DSP's reply status */ + + /* Make sure the DSP Id is valid. */ + if (DspId >= MAX_DSP_CORES) + return (RstfInvalidDsp); + + MsgBuffer[0] = (MSG_RESET_FRAME_STATS << 8); + + /* Attempt to send the message to the DSP and receive it's reply. */ + //need_reply_len; + if (!TransactCmd(DspId, MsgBuffer, 2, MSG_RESET_FRAME_STATS_REPLY, 4, 0, 0)) + return (RstfDspCommFailure); + + /* Return with an indication of success or failure based on the return + status in the reply message. */ + DspStatus = (MsgBuffer[1] & 0xFF); + if (DspStatus == 0) + return (RstfSuccess); + else + return (RstfDspCommFailure); +} + +/* + * gpakDownloadDsp - Download a DSP's Program and initialized Data memory. + * + * FUNCTION + * This function reads a DSP's Program and Data memory image from the + * specified file and writes the image to the DSP's memory. + * + * RETURNS + * Status code indicating success or a specific error. + * + */ +gpakDownloadStatus_t gpakDownloadDsp( + unsigned short DspId, /* DSP Identifier (0 to MaxDSPCores-1) */ + GPAK_FILE_ID FileId /* G.PAK Download File Identifier */ + ) +{ + gpakDownloadStatus_t RetStatus; /* function return status */ + int NumRead; /* number of file bytes read */ + DSP_ADDRESS Address; /* DSP address */ + unsigned int WordCount; /* number of words in record */ + unsigned int NumWords; /* number of words to read/write */ + unsigned int i; /* loop index / counter */ + unsigned int j; /* loop index */ + + /* Make sure the DSP Id is valid. */ + if (DspId >= MAX_DSP_CORES) + return (GdlInvalidDsp); + + /* Lock access to the DSP. */ + gpakLockAccess(DspId); + + RetStatus = GdlSuccess; + while (RetStatus == GdlSuccess) + { + + /* Read a record header from the file. */ + NumRead = gpakReadFile(FileId, DlByteBufr, 6); + if (NumRead == -1) + { + RetStatus = GdlFileReadError; + break; + } + if (NumRead != 6) + { + RetStatus = GdlInvalidFile; + break; + } + Address = (((DSP_ADDRESS) DlByteBufr[1]) << 16) | + (((DSP_ADDRESS) DlByteBufr[2]) << 8) | + ((DSP_ADDRESS) DlByteBufr[3]); + WordCount = (((unsigned int) DlByteBufr[4]) << 8) | + ((unsigned int) DlByteBufr[5]); + + /* Check for the End Of File record. */ + if (DlByteBufr[0] == 0xFF) + break; + + /* Verify the record is for a valid memory type. */ + if ((DlByteBufr[0] != 0x00) && (DlByteBufr[0] != 0x01)) + { + RetStatus = GdlInvalidFile; + break; + } + + /* Read a block of words at a time from the file and write to the + DSP's memory .*/ + while (WordCount != 0) + { + if (WordCount < DOWNLOAD_BLOCK_SIZE) + NumWords = WordCount; + else + NumWords = DOWNLOAD_BLOCK_SIZE; + WordCount -= NumWords; + NumRead = gpakReadFile(FileId, DlByteBufr, NumWords * 2); + if (NumRead == -1) + { + RetStatus = GdlFileReadError; + break; + } + if (NumRead != (NumWords * 2)) + { + RetStatus = GdlInvalidFile; + break; + } + for (i = 0, j = 0; i < NumWords; i++, j += 2) + DlWordBufr[i] = (((DSP_WORD) DlByteBufr[j]) << 8) | + ((DSP_WORD) DlByteBufr[j + 1]); + gpakWriteDspMemory(DspId, Address, NumWords, DlWordBufr); + Address += ((DSP_ADDRESS) NumWords); + } + } + + /* Unlock access to the DSP. */ + gpakUnlockAccess(DspId); + + /* Return with an indication of success or failure. */ + return (RetStatus); +} + +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + * gpakReadCpuUsage - Read CPU usage statistics from a DSP. + * + * FUNCTION + * This function reads the memory map register section of DSP memory. + * + * RETURNS + * Status code indicating success or a specific error. + * + */ +gpakReadDSPMemoryStat_t gpakReadDSPMemoryMap( + unsigned short int DspId, // Dsp Identifier + unsigned short int *pDest, // Buffer on host to hold DSP memory map + DSP_ADDRESS BufrBaseAddress, // DSP memory users want to read out + unsigned short int MemoryLength_Word16 // Length of memory section read out, unit is 16-bit word + ) +{ + DSP_WORD MsgBuffer[MSG_BUFFER_SIZE]; /* message buffer */ + DSP_WORD DspStatus; /* DSP reply's status */ + int i; /* loop index / counter */ + + + /* Make sure the DSP Id is valid. */ + if (DspId >= MAX_DSP_CORES) + return (RmmInvalidDsp); + + /* Verify the message buffer is large enough */ + if (MSG_BUFFER_SIZE < MemoryLength_Word16 ) + return (RmmSizeTooBig); + + MsgBuffer[0] = MSG_READ_DSP_MEMORY << 8; + MsgBuffer[1] = (DSP_WORD) ((BufrBaseAddress >> 16) & 0xFFFF); + MsgBuffer[2] = (DSP_WORD) (BufrBaseAddress & 0xFFFF); + MsgBuffer[3] = (DSP_WORD) MemoryLength_Word16; + + /* Attempt to send the Read memory section message to the DSP and receive it's + reply. */ + //need_reply_len; + if (!TransactCmd(DspId, MsgBuffer, 8, MSG_READ_DSP_MEMORY_REPLY, + (MemoryLength_Word16+2)*2, 0, 0) ) + return (RmmInvalidAddress); + + /* Return with an indication of success or failure based on the return + status in the reply message. */ + DspStatus = (MsgBuffer[1] & 0xFF); + if (DspStatus != 0) + return (RmmFailure); + + for (i = 0; i < MemoryLength_Word16; i++) + pDest[i] = (short int) MsgBuffer[2 + i]; + + + return (RmmSuccess); +} + +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + * gpakAccessGPIO - change Direction/read/write the GPIO on DSP + * + * FUNCTION + * This function read/write GPIO and change the GPIO direction + * + * + * RETURNS + * Status code indicating success or a specific error. + */ +gpakAccessGPIOStat_t gpakAccessGPIO( + unsigned short int DspId, // DSP identifier + GpakGPIOCotrol_t gpakControlGPIO,// select oeration, changeDIR/write/read + unsigned short int *pGPIOValue // DSP software version + ) +{ + DSP_WORD MsgBuffer[MSG_BUFFER_SIZE]; /* message buffer */ + DSP_WORD DspStatus; /* DSP's reply status */ + + /* Make sure the DSP Id is valid. */ + if (DspId >= MAX_DSP_CORES) + return (GPIOInvalidDsp); + + /* send value of 1, DSP increments it */ + MsgBuffer[0] = (MSG_ACCESSGPIO << 8); + MsgBuffer[1] = (DSP_WORD) ((gpakControlGPIO << 8) | (*pGPIOValue & 0xFF) ); + /* Attempt to send the ping message to the DSP and receive it's + reply. */ + if (!TransactCmd(DspId, MsgBuffer, 4, MSG_ACCESSGPIO_REPLY, 6, 0, 0)) + return (GPIODspCommFailure); + + /* Return with an indication of success or failure based on the return + status in the reply message. */ + DspStatus = (MsgBuffer[1] & 0xFF); + if (DspStatus == 0) + { + *pGPIOValue = MsgBuffer[2]; + return (GPIOSuccess); + } + else + return (GPIODspCommFailure); +} + +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + * gpakWriteSystemParms - Write a DSP's System Parameters. + * + * FUNCTION + * This function writes a DSP's System Parameters information. + * + * Note: + * Or-together the desired bit-mask #defines that are listed below. Only + * those algorithm parameters whose bit-mask is selected in the UpdateBits + * function parameter will be updated. + * + * RETURNS + * Status code indicating success or a specific error. + * + */ + +gpakWriteSysParmsStatus_t gpakWriteSystemParms( + unsigned short int DspId, // DSP identifier + GpakSystemParms_t *pSysParms, /* pointer to System Parms info var */ + unsigned short int UpdateBits, /* input: flags indicating which parms to update */ + GPAK_SysParmsStat_t *pStatus /* pointer to Write System Parms Status */ + ) +{ + DSP_WORD MsgBuffer[MSG_BUFFER_SIZE]; /* message buffer */ + DSP_WORD DspStatus; /* DSP's reply status */ + + /* Make sure the DSP Id is valid. */ + if (DspId >= MAX_DSP_CORES) + return (WspInvalidDsp); + + /* Build the Write System Parameters message. */ + MsgBuffer[0] = MSG_WRITE_SYS_PARMS << 8; + + if (UpdateBits & DTMF_UPDATE_MASK) + { + MsgBuffer[1] |= DTMF_UPDATE_MASK; + MsgBuffer[8] = (DSP_WORD) pSysParms->MinSigLevel; + MsgBuffer[9] = (DSP_WORD) (pSysParms->FreqDeviation & 0xff); + if (pSysParms->SNRFlag) + MsgBuffer[9] |= (1<<8); + } + + MsgBuffer[10] = (DSP_WORD) 0; + if (UpdateBits & DTMF_TWIST_UPDATE_MASK) + { + MsgBuffer[1] |= DTMF_TWIST_UPDATE_MASK; + MsgBuffer[10] |= (DSP_WORD) (pSysParms->DtmfFwdTwist & 0x000f); + MsgBuffer[10] |= (DSP_WORD) ((pSysParms->DtmfRevTwist << 4) & 0x00f0); + } + + + if (UpdateBits & DTMF_VALID_MASK) + { + MsgBuffer[1] |= DTMF_VALID_MASK; + MsgBuffer[11] = (DSP_WORD) (pSysParms->DtmfValidityMask & 0x00ff); + } + + /* Attempt to send the ping message to the DSP and receive it's + reply. */ + if (!TransactCmd(DspId, MsgBuffer, 24, MSG_WRITE_SYS_PARMS_REPLY, 6, 0, 0)) + return (WspDspCommFailure); + + /* Return with an indication of success or failure based on the return + status in the reply message. */ + *pStatus = (GPAK_SysParmsStat_t) (MsgBuffer[2] ); + + DspStatus = (MsgBuffer[1] & 0xFF); + if (DspStatus == 0) + return (WspSuccess); + else + return (WspDspCommFailure); +} + +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + * gpakReadSystemParms - Read a DSP's System Parameters. + * + * FUNCTION + * This function reads a DSP's System Parameters information. + * + * RETURNS + * Status code indicating success or a specific error. + * + */ +gpakReadSysParmsStatus_t gpakReadSystemParms( + unsigned short int DspId, // DSP identifier + GpakSystemParms_t *pSysParms /* pointer to System Parms info var */ + ) +{ + + DSP_WORD MsgBuffer[MSG_BUFFER_SIZE]; /* message buffer */ + + /* Make sure the DSP Id is valid. */ + if (DspId >= MAX_DSP_CORES) + return (RspInvalidDsp); + + /* Build the Read System Parameters message. */ + MsgBuffer[0] = MSG_READ_SYS_PARMS << 8; + + /* Attempt to send the ping message to the DSP and receive it's + reply. */ + if (!TransactCmd(DspId, MsgBuffer, 2, MSG_READ_SYS_PARMS_REPLY, 22, 0, 0)) + return (RspDspCommFailure); + + /* Extract the System Parameters information from the message. */ + pSysParms->DtmfValidityMask = (short int)(MsgBuffer[7]) ; + + pSysParms->MinSigLevel = (short int)MsgBuffer[8]; + pSysParms->SNRFlag = (short int)((MsgBuffer[9]>>8) & 0x1); + pSysParms->FreqDeviation = (short int)(MsgBuffer[9] & 0xff); + pSysParms->DtmfFwdTwist = (short int)MsgBuffer[10] & 0x000f; + pSysParms->DtmfRevTwist = (short int)(MsgBuffer[10] >> 4) & 0x000f; + + /* Return with an indication that System Parameters info was obtained. */ + return (RspSuccess); +} +#endif diff -uNr zaptel-1.4.8/wcte12xp/.svn/text-base/GpakApi.h.svn-base zaptel-1.4/wcte12xp/.svn/text-base/GpakApi.h.svn-base --- zaptel-1.4.8/wcte12xp/.svn/text-base/GpakApi.h.svn-base 1970-01-01 01:00:00.000000000 +0100 +++ zaptel-1.4/wcte12xp/.svn/text-base/GpakApi.h.svn-base 2008-02-03 17:46:02.000000000 +0100 @@ -0,0 +1,637 @@ +/* + * Copyright (c) 2005 , Adaptive Digital Technologies, Inc. + * + * File Name: GpakApi.h + * + * Description: + * This file contains the function prototypes and data types for the user + * API functions that communicate with DSPs executing G.PAK software. The + * file is used by application software in the host processor connected to + * C55X G.PAK DSPs via a Host Port Interface. + * + * Version: 1.0 + * + * Revision History: + * 06/15/05 - Initial release. + * 11/15/2006 - 24 TDM-TDM Channels EC release + * + * This program has been released under the terms of the GPL version 2 by + * permission of Adaptive Digital Technologies, Inc. The standard + * GPL disclaimer is given inline below for your convenience. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef _GPAKAPI_H /* prevent multiple inclusion */ +#define _GPAKAPI_H +#include "GpakErrs.h" +#include "gpakenum.h" + +// Bit masks to select which algorithm's parameters to update: Or-together the +// desired masks into the UpdateBits function parameter. +#define DTMF_UPDATE_MASK 0x0010 // update DTMF params, MinLevel, SNRFlag and Freq +#define DTMF_TWIST_UPDATE_MASK 0x0020 // update DTMF TWIST system params +#define DTMF_VALID_MASK 0x0080 // update DTMF ValidMask params + +#define DSP_DEBUG_BUFF_SIZE 42 // units of 16-bit words + +/* Definition of an Asynchronous Event Data Structure */ +typedef union +{ + struct + { + GpakToneCodes_t ToneCode; // detected tone code + unsigned short int ToneDuration; // tone duration + GpakTdmDirection Direction; // detected on A r B side + short int DebugToneStatus;// reserved for debug info + } toneEvent; + +} GpakAsyncEventData_t; + +/* Definition of an Echo Canceller Parameters information structure. */ +typedef struct +{ + short int EcanTapLength; // Echo Can Num Taps (tail length) + short int EcanNlpType; // Echo Can NLP Type + short int EcanAdaptEnable; // Echo Can Adapt Enable flag + short int EcanG165DetEnable; // Echo Can G165 Detect Enable flag + short int EcanDblTalkThresh; // Echo Can Double Talk threshold + short int EcanNlpThreshold; // Echo Can NLP threshold + short int EcanNlpConv; // Dynamic NLP control, NLP limit when EC about to converged + short int EcanNlpUnConv;// Dynamic NLP control, NLP limit when EC not converged yet + short int EcanNlpMaxSuppress; // suppression level for NLP_SUPP mode + short int EcanCngThreshold; // Echo Can CNG Noise threshold + short int EcanAdaptLimit; // Echo Can Max Adapts per frame + short int EcanCrossCorrLimit; // Echo Can Cross Correlation limit + short int EcanNumFirSegments; // Echo Can Num FIR Segments + short int EcanFirSegmentLen; // Echo Can FIR Segment Length +} GpakEcanParms_t; + +/* Definition of a Channel Configuration information structure. */ +typedef struct +{ + GpakSerialPort_t PcmInPortA; // A side PCM Input Serial Port Id + unsigned short int PcmInSlotA; // A side PCM Input Time Slot + GpakSerialPort_t PcmOutPortA; // A side PCM Output Serial Port Id + unsigned short int PcmOutSlotA; // A side PCM Output Time Slot + GpakSerialPort_t PcmInPortB; // B side PCM Input Serial Port Id + unsigned short int PcmInSlotB; // B side PCM Input Time Slot + GpakSerialPort_t PcmOutPortB; // B side PCM Output Serial Port Id + unsigned short int PcmOutSlotB; // B side PCM Output Time Slot + GpakToneTypes ToneTypesA; // A side Tone Detect Types + GpakToneTypes ToneTypesB; // B side Tone Detect Types + GpakActivation EcanEnableA; // Echo Cancel A Enabled + GpakActivation EcanEnableB; // Echo Cancel B Enabled + GpakEcanParms_t EcanParametersA; // Echo Cancel parameters + GpakEcanParms_t EcanParametersB; // Echo Cancel parameters + GpakCompandModes SoftwareCompand; // software companding + GpakRate_t FrameRate; // Gpak Frame Rate + GpakActivation MuteToneA; // A side mute DTMF Enabled + GpakActivation MuteToneB; // B side mute DTMF Enabled + GpakActivation FaxCngDetA; // A side FaxCng Tone Detector Enabled + GpakActivation FaxCngDetB; // B side FaxCng Tone Detector Enabled + +} GpakChannelConfig_t; + + +/* Definition of a Serial Port Configuration Structure */ +typedef struct +{ + GpakSlotCfg_t SlotsSelect1; // port 1 Slot selection + unsigned short int FirstBlockNum1; // port 1 first group Block Number + unsigned short int FirstSlotMask1; // port 1 first group Slot Mask + unsigned short int SecBlockNum1; // port 1 second group Block Number + unsigned short int SecSlotMask1; // port 1 second group Slot Mask + + GpakSerWordSize_t SerialWordSize1; // port 1 serial word size + GpakCompandModes CompandingMode1; // port 1 companding mode + GpakSerFrameSyncPol_t TxFrameSyncPolarity1; // port 1 Tx Frame Sync Polarity + GpakSerFrameSyncPol_t RxFrameSyncPolarity1; // port 1 Rx Frame Sync Polarity + GpakSerClockPol_t TxClockPolarity1; // port 1 Tx Clock Polarity + GpakSerClockPol_t RxClockPolarity1; // port 1 Rx Clock Polarity + GpakSerDataDelay_t TxDataDelay1; // port 1 Tx data delay + GpakSerDataDelay_t RxDataDelay1; // port 1 Rx data delay + GpakActivation DxDelay1; // port 1 DX Delay + + unsigned short int ThirdSlotMask1; // port 1 3rd group Slot Mask + unsigned short int FouthSlotMask1; // port 1 4th group Slot Mask + unsigned short int FifthSlotMask1; // port 1 5th group Slot Mask + unsigned short int SixthSlotMask1; // port 1 6th group Slot Mask + unsigned short int SevenSlotMask1; // port 1 7th group Slot Mask + unsigned short int EightSlotMask1; // port 1 8th group Slot Mask + + + GpakSlotCfg_t SlotsSelect2; // port 2 Slot selection + unsigned short int FirstBlockNum2; // port 2 first group Block Number + unsigned short int FirstSlotMask2; // port 2 first group Slot Mask + unsigned short int SecBlockNum2; // port 2 second group Block Number + unsigned short int SecSlotMask2; // port 2 second group Slot Mask + GpakSerWordSize_t SerialWordSize2; // port 2 serial word size + GpakCompandModes CompandingMode2; // port 2 companding mode + GpakSerFrameSyncPol_t TxFrameSyncPolarity2; // port 2 Tx Frame Sync Polarity + GpakSerFrameSyncPol_t RxFrameSyncPolarity2; // port 2 Rx Frame Sync Polarity + GpakSerClockPol_t TxClockPolarity2; // port 2 Tx Clock Polarity + GpakSerClockPol_t RxClockPolarity2; // port 2 Rx Clock Polarity + GpakSerDataDelay_t TxDataDelay2; // port 2 Tx data delay + GpakSerDataDelay_t RxDataDelay2; // port 2 Rx data delay + GpakActivation DxDelay2; // port 2 DX Delay + + unsigned short int ThirdSlotMask2; // port 2 3rd group Slot Mask + unsigned short int FouthSlotMask2; // port 2 4th group Slot Mask + unsigned short int FifthSlotMask2; // port 2 5th group Slot Mask + unsigned short int SixthSlotMask2; // port 2 6th group Slot Mask + unsigned short int SevenSlotMask2; // port 2 7th group Slot Mask + unsigned short int EightSlotMask2; // port 2 8th group Slot Mask + + GpakSlotCfg_t SlotsSelect3; // port 3 Slot selection + unsigned short int FirstBlockNum3; // port 3 first group Block Number + unsigned short int FirstSlotMask3; // port 3 first group Slot Mask + unsigned short int SecBlockNum3; // port 3 second group Block Number + unsigned short int SecSlotMask3; // port 3 second group Slot Mask + GpakSerWordSize_t SerialWordSize3; // port 3 serial word size + GpakCompandModes CompandingMode3; // port 3 companding mode + GpakSerFrameSyncPol_t TxFrameSyncPolarity3; // port 3 Tx Frame Sync Polarity + GpakSerFrameSyncPol_t RxFrameSyncPolarity3; // port 3 Rx Frame Sync Polarity + GpakSerClockPol_t TxClockPolarity3; // port 3 Tx Clock Polarity + GpakSerClockPol_t RxClockPolarity3; // port 3 Rx Clock Polarity + GpakSerDataDelay_t TxDataDelay3; // port 3 Tx data delay + GpakSerDataDelay_t RxDataDelay3; // port 3 Rx data delay + GpakActivation DxDelay3; // port 3 DX Delay + + unsigned short int ThirdSlotMask3; // port 3 3rd group Slot Mask + unsigned short int FouthSlotMask3; // port 3 4th group Slot Mask + unsigned short int FifthSlotMask3; // port 3 5th group Slot Mask + unsigned short int SixthSlotMask3; // port 3 6th group Slot Mask + unsigned short int SevenSlotMask3; // port 3 7th group Slot Mask + unsigned short int EightSlotMask3; // port 3 8th group Slot Mask + +} GpakPortConfig_t; + +/* Definition of a Tone Generation Parameter Structure */ +/* +typedef struct +{ + GpakToneGenType_t ToneType; // Tone Type + unsigned short int Frequency[4]; // Frequency (Hz) + short int Level[4]; // Frequency's Level (1 dBm) + unsigned short int OnTime[4]; // On Times (msecs) + unsigned short int OffTime[4]; // Off Times (msecs) +} GpakToneGenParms_t; +*/ +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ + +/* gpakConfigureChannel return status. */ +typedef enum +{ + CcsSuccess = 0, /* Channel Configured successfully */ + CcsParmError = 1, /* Channel Config Parameter error */ + CcsInvalidChannel = 2, /* invalid channel */ + CcsInvalidDsp = 3, /* invalid DSP */ + CcsDspCommFailure = 4 /* failed to communicate with DSP */ +} gpakConfigChanStatus_t; + +/* + * gpakConfigureChannel - Configure a DSP's Channel. + * + * FUNCTION + * This function configures a DSP's Channel. + * + * RETURNS + * Status code indicating success or a specific error. + * + */ +extern gpakConfigChanStatus_t gpakConfigureChannel( + unsigned short int DspId, // DSP identifier + unsigned short int ChannelId, // channel identifier + GpakChanType ChannelType, // channel type + GpakChannelConfig_t *pChanConfig, // pointer to channel config info + GPAK_ChannelConfigStat_t *pStatus // pointer to Channel Config Status + ); + + +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ + +/* gpakTearDownChannel return status. */ +typedef enum +{ + TdsSuccess = 0, /* Channel Tear Down successful */ + TdsError = 1, /* Channel Tear Down error */ + TdsInvalidChannel = 2, /* invalid channel */ + TdsInvalidDsp = 3, /* invalid DSP */ + TdsDspCommFailure = 4 /* failed to communicate with DSP */ +} gpakTearDownStatus_t; + +/* + * gpakTearDownChannel - Tear Down a DSP's Channel. + * + * FUNCTION + * This function tears down a DSP's Channel. + * + * RETURNS + * Status code indicating success or a specific error. + * + */ + +extern gpakTearDownStatus_t gpakTearDownChannel( + unsigned short int DspId, // DSP identifier + unsigned short int ChannelId, // channel identifier + GPAK_TearDownChanStat_t *pStatus // pointer to Tear Down Status + ); + +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ + +/* gpakAlgControl return status. */ +typedef enum +{ + AcSuccess = 0, /* control successful */ + AcInvalidChannel = 1, /* invalid channel identifier */ + AcInvalidDsp = 2, /* invalid DSP */ + AcParmError = 3, /* invalid control parameter */ + AcDspCommFailure = 4 /* failed to communicate with DSP */ +} gpakAlgControlStat_t; + +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + * gpakAlgControl - Control an Algorithm. + * + * FUNCTION + * This function controls an Algorithm + * + * RETURNS + * Status code indicating success or a specific error. + * + */ +extern gpakAlgControlStat_t gpakAlgControl( + unsigned short int DspId, // DSP identifier + unsigned short int ChannelId, // channel identifier + GpakAlgCtrl_t ControlCode, // algorithm control code + GPAK_AlgControlStat_t *pStatus // pointer to return status + ); + + +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ + +/* gpakConfigurePorts return status. */ +typedef enum +{ + CpsSuccess = 0, /* Serial Ports configured successfully */ + CpsParmError = 1, /* Configure Ports Parameter error */ + CpsInvalidDsp = 2, /* invalid DSP */ + CpsDspCommFailure = 3 /* failed to communicate with DSP */ +} gpakConfigPortStatus_t; + +/* + * gpakConfigurePorts - Configure a DSP's serial ports. + * + * FUNCTION + * This function configures a DSP's serial ports. + * + * RETURNS + * Status code indicating success or a specific error. + * + */ +extern gpakConfigPortStatus_t gpakConfigurePorts( + unsigned short int DspId, // DSP identifier + GpakPortConfig_t *pPortConfig, // pointer to Port Config info + GPAK_PortConfigStat_t *pStatus // pointer to Port Config Status + ); + +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ + +/* gpakDownloadDsp return status. */ +typedef enum +{ + GdlSuccess = 0, /* DSP download successful */ + GdlFileReadError = 1, /* error reading Download file */ + GdlInvalidFile = 2, /* invalid Download file content */ + GdlInvalidDsp = 3 /* invalid DSP */ +} gpakDownloadStatus_t; + +/* + * gpakDownloadDsp - Download a DSP's Program and initialized Data memory. + * + * FUNCTION + * This function reads a DSP's Program and Data memory image from the + * specified file and writes the image to the DSP's memory. + * + * RETURNS + * Status code indicating success or a specific error. + * + */ +extern gpakDownloadStatus_t gpakDownloadDsp( + unsigned short int DspId, // DSP identifier + GPAK_FILE_ID FileId // G.PAK download file identifier + ); + +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ + +/* gpakReadEventFIFOMessage return status */ +typedef enum +{ + RefEventAvail = 0, /* an event was successfully read from the fifo */ + RefNoEventAvail = 1, /* no event was in the fifo */ + RefInvalidDsp = 2, /* invalid DSP identifier */ + RefInvalidEvent = 3, /* invalid event */ + RefDspCommFailure = 4 /* error communicating with DSP */ +} gpakReadEventFIFOMessageStat_t; + +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + * gpakReadEventFIFOMessage - read from the event fifo + * + * FUNCTION + * This function reads a single event from the event fifo if one is available + * + * RETURNS + * Status code indicating success or a specific error. + * + * Note: This function should be called in a loop until the return status + * indicates that the fifo is empty. + */ +extern gpakReadEventFIFOMessageStat_t gpakReadEventFIFOMessage( + unsigned short int DspId, // DSP identifier + unsigned short int *pChannelId, // pointer to channel identifier + GpakAsyncEventCode_t *pEventCode, // pointer to Event Code + GpakAsyncEventData_t *pEventData // pointer to Event Data Struct + ); + + +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/ + +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/ + +/* gpakPingDsp return status values */ +typedef enum +{ + PngSuccess = 0, /* DSP responded successfully */ + PngInvalidDsp = 1, /* invalid DSP identifier */ + PngDspCommFailure = 2 /* error communicating with DSP */ +} gpakPingDspStat_t; + +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + * gpakPingDsp - ping the DSP to see if it's alive + * + * FUNCTION + * This function checks if the DSP is still communicating with the host + * + * RETURNS + * Status code indicating success or a specific error. + */ +extern gpakPingDspStat_t gpakPingDsp( + unsigned short int DspId, // DSP identifier + unsigned short int *pDspSwVersion // DSP software version + ); + +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/ + +/* gpakSerialTxFixedValue return status values */ +typedef enum +{ + TfvSuccess = 0, /* operation successful */ + TfvInvalidChannel = 1, /* invalid channel identifier */ + TfvInvalidDsp = 2, /* invalid DSP identifier */ + TfvDspCommFailure = 3 /* failed to communicate with DSP */ +} gpakSerialTxFixedValueStat_t; + +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + * gpakSerialTxFixedValue - transmit a fixed value on a timeslot + * + * FUNCTION + * This function controls transmission of a fixed value out onto a serial + * port's timeslot. + * + * RETURNS + * Status code indicating success or a specific error. + */ +extern gpakSerialTxFixedValueStat_t gpakSerialTxFixedValue( + unsigned short int DspId, // DSP identifier + unsigned short int ChannelId, // channel identifier + GpakSerialPort_t PcmOutPort, // PCM Output Serial Port Id + unsigned short int PcmOutSlot, // PCM Output Time Slot + unsigned short int Value, // 16-bit value + GpakActivation State // activation state + ); + +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/ + +/* gpakControlTdmLoopBack return status values */ +typedef enum +{ + ClbSuccess = 0, /* operation successful */ + ClbSerPortInactive = 1, /* serial port is inactive */ + ClbInvalidDsp = 2, /* invalid DSP identifier */ + ClbDspCommFailure = 3 /* failed to communicate with DSP */ +} gpakControlTdmLoopBackStat_t; + +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + * gpakControlTdmLoopBack - control a serial port's loopback state + * + * FUNCTION + * This function enables/disables the tdm input to output looback mode on a + * serial port + * + * RETURNS + * Status code indicating success or a specific error. + */ + +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/ +gpakControlTdmLoopBackStat_t gpakControlTdmLoopBack( + unsigned short int DspId, // DSP identifier + GpakSerialPort_t SerialPort, // Serial Port Id + GpakActivation LoopBackState // Loopback State + ); + +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/ + +/* gpakReadCpuUsage return status values */ +typedef enum +{ + RcuSuccess = 0, /* operation successful */ + RcuInvalidDsp = 1, /* invalid DSP identifier */ + RcuDspCommFailure = 2 /* communication failure */ +} gpakReadCpuUsageStat_t; + +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + * gpakReadCpuUsage - read the cpu usage statistics + * + * FUNCTION + * This function reads cpu utilization from the DSP. + * + * RETURNS + * Status code indicating success or a specific error. + */ +extern gpakReadCpuUsageStat_t gpakReadCpuUsage( + unsigned short int DspId, // DSP identifier + unsigned short int *pPeakUsage, // pointer to peak usage variable + unsigned short int *pPrev1SecPeakUsage // peak usage over previous 1 second + ); + +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/ + +/* gpakResetCpuUsageStats return status values */ +typedef enum +{ + RstcSuccess = 0, /* operation successful */ + RstcInvalidDsp = 1, /* invalid DSP identifier */ + RstcDspCommFailure = 2 /* communication failure */ +} gpakResetCpuUsageStat_t; +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + * gpakResetCpuUsageStats - reset the cpu usage statistics + * + * FUNCTION + * This function resets the cpu utilization statistics + * + * RETURNS + * Status code indicating success or a specific error. + */ +extern gpakResetCpuUsageStat_t gpakResetCpuUsageStats( + unsigned short int DspId // DSP identifier + ); + + +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/ + +/* gpakReadFramingStats return status values */ +typedef enum +{ + RfsSuccess = 0, /* operation successful */ + RfsInvalidDsp = 1, /* invalid DSP identifier */ + RfsDspCommFailure = 2 /* communication failure */ +} gpakReadFramingStatsStatus_t; + +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + * gpakReadFramingStats + * + * FUNCTION + * This function reads a DSP's framing interrupt statistics + * + * RETURNS + * Status code indicating success or a specific error. + */ +extern gpakReadFramingStatsStatus_t gpakReadFramingStats( + unsigned short int DspId, // DSP identifier + unsigned short int *pFramingError1Count, // port 1 Framing error count + unsigned short int *pFramingError2Count, // port 2 Framing error count + unsigned short int *pFramingError3Count, // port 3 Framing error count + unsigned short int *pDmaStopErrorCount, // DMA-stoppage error count + unsigned short int *pDmaSlipStatsBuffer // DMA slips count + ); + +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/ + +/* gpakResetFramingStats return values */ +typedef enum +{ + RstfSuccess = 0, /* operation successful */ + RstfInvalidDsp = 1, /* invalid DSP identifier */ + RstfDspCommFailure = 2 /* communication failure */ +} gpakResetFramingStatsStatus_t; + +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + * gpakResetFramingStats - reset a DSP's framing interrupt statistics + * + * FUNCTION + * This function resets a DSP's framing interrupt statistics + * + * RETURNS + * Status code indicating success or a specific error. + */ +extern gpakResetFramingStatsStatus_t gpakResetFramingStats( + unsigned short int DspId // DSP identifier + ); + + +typedef enum +{ + RmmSuccess =0, + RmmInvalidDsp = 1, + RmmSizeTooBig = 2, + RmmFailure = 3, + RmmInvalidAddress = 4 + +} gpakReadDSPMemoryStat_t; +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + * gpakResetFramingStats - read a section of DSP memory + * to get access DSP registers, since 0x00--0x60 not HPI-accessable + * + * FUNCTION + * This function resets a DSP's framing interrupt statistics + * + * RETURNS + * Status code indicating success or a specific error. + */ + +extern gpakReadDSPMemoryStat_t gpakReadDSPMemoryMap( + unsigned short int DspId, // Dsp Identifier + unsigned short int *pDest, // Buffer on host to hold DSP memory map + DSP_ADDRESS BufrBaseAddress, // DSP memory users want to read out + unsigned short int MemoryLength_Word16 // Length of memory section read out, unit is 16-bit word + ); + +typedef enum +{ + GPIOSuccess =0, + GPIOInvalidDsp = 1, + GPIODspCommFailure = 2 +}gpakAccessGPIOStat_t; + +extern gpakAccessGPIOStat_t gpakAccessGPIO( + unsigned short int DspId, // DSP identifier + GpakGPIOCotrol_t gpakControlGPIO,// select oeration, changeDIR/write/read + unsigned short int *pGPIOValue // pointer for the read/write value or DIR mask + ); + +/* gpakWriteSystemParms return status. */ +typedef enum +{ + WspSuccess = 0, /* System Parameters written successfully */ + WspParmError = 1, /* Write System Parms's Parameter error */ + WspInvalidDsp = 2, /* invalid DSP */ + WspDspCommFailure = 3 /* failed to communicate with DSP */ +} gpakWriteSysParmsStatus_t; + +/* Definition of a System Parameters information structure. */ +typedef struct +{ + /* DTMF Parameters */ + short int MinSigLevel; /* 0 = Disabled, Min Sig Power Level for detection */ + short int SNRFlag; /* 0 = Disabled, relax SNR tolerances */ + short int FreqDeviation; /* 0 = Disabled, X Percent Deviation times 10 (e.g. 1.7% is entered as 17) */ + short int DtmfFwdTwist; /* 0 to 8 db */ + short int DtmfRevTwist; /* 0 to 8 db */ + + short int DtmfValidityMask; /* This flag allows users to relax the trailing conditions of the tone */ + +} GpakSystemParms_t; +/* gpakReadSystemParms return status. */ +typedef enum +{ + RspSuccess = 0, /* System Parameters read successfully */ + RspInvalidDsp = 1, /* invalid DSP */ + RspDspCommFailure = 2 /* failed to communicate with DSP */ +} gpakReadSysParmsStatus_t; + +extern gpakReadSysParmsStatus_t gpakReadSystemParms( + unsigned short int DspId, // DSP identifier + GpakSystemParms_t *pSysParms /* pointer to System Parms info var */ + ); + +extern gpakWriteSysParmsStatus_t gpakWriteSystemParms( + unsigned short int DspId, // DSP identifier + GpakSystemParms_t *pSysParms, /* pointer to System Parms info var */ + unsigned short int UpdateBits, /* input: flags indicating which parms to update */ + GPAK_SysParmsStat_t *pStatus /* pointer to Write System Parms Status */ + ); + +#endif // end multiple inclusion + diff -uNr zaptel-1.4.8/wcte12xp/.svn/text-base/gpakenum.h.svn-base zaptel-1.4/wcte12xp/.svn/text-base/gpakenum.h.svn-base --- zaptel-1.4.8/wcte12xp/.svn/text-base/gpakenum.h.svn-base 1970-01-01 01:00:00.000000000 +0100 +++ zaptel-1.4/wcte12xp/.svn/text-base/gpakenum.h.svn-base 2008-02-03 17:46:02.000000000 +0100 @@ -0,0 +1,191 @@ +/* + * Copyright (c) 2005, Adaptive Digital Technologies, Inc. + * + * File Name: gpakenum.h + * + * Description: + * This file contains common enumerations related to G.PAK application + * software. + * + * Version: 1.0 + * + * Revision History: + * 06/15/05 - Initial release. + * + * This program has been released under the terms of the GPL version 2 by + * permission of Adaptive Digital Technologies, Inc. The standard + * GPL disclaimer is given inline below for your convenience. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef _GPAKENUM_H /* prevent multiple inclusion */ +#define _GPAKENUM_H + +/* G.PAK Serial Port Word Size */ +typedef enum +{ + SerWordSize8 = 0, // 8-bit seial word + SerWordSize16 = 1 // 16-bit serial word +} GpakSerWordSize_t; + +/* G.PAK Serial Port FrameSync Polarity */ +typedef enum +{ + FrameSyncActLow = 0, // active low frame sync signal + FrameSyncActHigh = 1 // active high frame sync signal +} GpakSerFrameSyncPol_t; + +/* G.PAK Serial Port Clock Polarity */ +typedef enum +{ + SerClockActLow = 0, // active low serial clock + SerClockActHigh = 1 // active high serial clock +} GpakSerClockPol_t; + +/* G.PAK Serial Port Data Delay */ +typedef enum +{ + DataDelay0 = 0, // no data delay + DataDelay1 = 1, // 1-bit data delay + DataDelay2 = 2 // 2-bit data delay +} GpakSerDataDelay_t; + +/* G.PAK Serial Port Ids. */ +typedef enum +{ + SerialPortNull = 0, // null serial port + SerialPort1 = 1, // first PCM serial stream port (McBSP0) + SerialPort2 = 2, // second PCM serial stream port (McBSP1) + SerialPort3 = 3 // third PCM serial stream port (McBSP2) +} GpakSerialPort_t; + +/* G.PAK serial port Slot Configuration selection codes. */ +typedef enum +{ + SlotCfgNone = 0, // no time slots used + SlotCfg2Groups = 2, // 2 groups of 16 time slots used, 32 Channels system + SlotCfg8Groups = 8 // 8-partition mode for 128-channel system +} GpakSlotCfg_t; + +/* G.PAK serial port Companding Mode codes. */ +typedef enum +{ + cmpPCMU=0, // u-Law + cmpPCMA=1, // A-Law + cmpNone=2 // none +} GpakCompandModes; + +/* G.PAK Active/Inactive selection codes. */ +typedef enum +{ + Disabled=0, // Inactive + Enabled=1 // Active +} GpakActivation; + +/* G.PAK Channel Type codes. */ +typedef enum +{ + inactive=0, // channel inactive + tdmToTdm=1 // tdmToTdm +} GpakChanType; + +/* G.PAK Algorithm control commands */ +typedef enum +{ + EnableEcanA = 0, // Enable A side echo canceller + BypassEcanA = 1, // Bypass A side echo canceller + ResetEcanA = 2, // Reset A side echo canceller + EnableEcanB = 3, // Enable B side echo canceller + BypassEcanB = 4, // Bypass B side echo canceller + ResetEcanB = 5, // Reset B side echo canceller + + EnableMuLawSwCompanding = 6,// Enable Mu-law Software companding + EnableALawSwCompanding = 7, // Enable Mu-law Software companding + BypassSwCompanding = 8, // Bypass Software companding + EnableDTMFMuteA = 9, // Mute A side Dtmf digit after tone detected + DisableDTMFMuteA = 10, // Do not mute A side Dtmf digit once tone detected + EnableDTMFMuteB = 11, // Mute B side Dtmf digit after tone detected + DisableDTMFMuteB = 12, // Do not mute B side Dtmf digit once tone detected + EnableFaxCngDetectA = 13, // Enable A side Fax CNG detector, channel must be configed already + DisableFaxCngDetectA = 14, // Disable A side Fax CNG detector, channel must be configed already + EnableFaxCngDetectB = 15, // Enable B side Fax CNG detector, channel must be configed already + DisableFaxCngDetectB = 16 // Disable B side Fax CNG detector, channel must be configed already +} GpakAlgCtrl_t; + +/* G.PAK Tone types. */ +typedef enum +{ + Null_tone = 0, // no tone detection + DTMF_tone = 1 // DTMF tone +} GpakToneTypes; + +/* G.PAK direction. */ +typedef enum +{ + TDMAToB = 0, // A to B + TDMBToA = 1 // B to A +} GpakTdmDirection; + + +typedef enum +{ + rate1ms=0, + rate2ms=1, + rate10ms=2 +} GpakRate_t; + +/* G.PAK Asynchronous Event Codes */ +typedef enum +{ + EventToneDetect = 0, // Tone detection event + EventDSPDebug = 7 // DSP debug data event +} GpakAsyncEventCode_t; + +/* G.PAK MF Tone Code Indices */ +typedef enum +{ + DtmfDigit1 = 0, // DTMF Digit 1 + DtmfDigit2 = 1, // DTMF Digit 2 + DtmfDigit3 = 2, // DTMF Digit 3 + DtmfDigitA = 3, // DTMF Digit A + DtmfDigit4 = 4, // DTMF Digit 4 + DtmfDigit5 = 5, // DTMF Digit 5 + DtmfDigit6 = 6, // DTMF Digit 6 + DtmfDigitB = 7, // DTMF Digit B + DtmfDigit7 = 8, // DTMF Digit 7 + DtmfDigit8 = 9, // DTMF Digit 8 + DtmfDigit9 = 10, // DTMF Digit 9 + DtmfDigitC = 11, // DTMF Digit C + DtmfDigitSt = 12, // DTMF Digit * + DtmfDigit0 = 13, // DTMF Digit 0 + DtmfDigitPnd = 14, // DTMF Digit # + DtmfDigitD = 15, // DTMF Digit D + + FaxCngDigit = 90, // Fax Calling Tone (1100 Hz) + + EndofMFDigit = 100, // End of MF digit + EndofCngDigit = 101 // End of Cng Digit +} GpakToneCodes_t; + +/* GPIO control code*/ +typedef enum +{ + GPIO_READ = 0, + GPIO_WRITE = 1, + GPIO_DIR = 2 +} GpakGPIOCotrol_t; + +#endif // end multiple inclusion diff -uNr zaptel-1.4.8/wcte12xp/.svn/text-base/GpakErrs.h.svn-base zaptel-1.4/wcte12xp/.svn/text-base/GpakErrs.h.svn-base --- zaptel-1.4.8/wcte12xp/.svn/text-base/GpakErrs.h.svn-base 1970-01-01 01:00:00.000000000 +0100 +++ zaptel-1.4/wcte12xp/.svn/text-base/GpakErrs.h.svn-base 2008-02-03 17:46:02.000000000 +0100 @@ -0,0 +1,156 @@ +/* + * Copyright (c) 2002 - 2004, Adaptive Digital Technologies, Inc. + * + * File Name: GpakErrs.h + * + * Description: + * This file contains DSP reply status codes used by G.PAK API functions to + * indicate specific errors. + * + * Version: 1.0 + * + * Revision History: + * 10/17/01 - Initial release. + * 07/03/02 - Updates for conferencing. + * 06/15/04 - Tone type updates. + * + * This program has been released under the terms of the GPL version 2 by + * permission of Adaptive Digital Technologies, Inc. The standard + * GPL disclaimer is given inline below for your convenience. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef _GPAKERRS_H /* prevent multiple inclusion */ +#define _GPAKERRS_H + +/* Configure Serial Ports reply status codes. */ +typedef enum +{ + Pc_Success = 0, /* serial ports configured successfully */ + Pc_ChannelsActive = 1, /* unable to configure while channels active */ + Pc_TooManySlots1 = 2, /* too many slots selected for port 1 */ + Pc_InvalidBlockCombo1 = 3, /* invalid combination of blocks for port 1 */ + Pc_NoSlots1 = 4, /* no slots selected for port 1 */ + Pc_InvalidSlots1 = 5, /* invalid slot (> max) selected for port 1 */ + Pc_TooManySlots2 = 6, /* too many slots selected for port 2 */ + Pc_InvalidBlockCombo2 = 7, /* invalid combination of blocks for port 2 */ + Pc_NoSlots2 = 8, /* no slots selected for port 2 */ + Pc_InvalidSlots2 = 9, /* invalid slot (> max) selected for port 2 */ + Pc_TooManySlots3 = 10, /* too many slots selected for port 3 */ + Pc_InvalidBlockCombo3 = 11, /* invalid combination of blocks for port 3 */ + Pc_NoSlots3 = 12, /* no slots selected for port 3 */ + Pc_InvalidSlots3 = 13 /* invalid slot (> max) selected for port 3 */ +} GPAK_PortConfigStat_t; + +/* Configure Channel reply status codes. */ +typedef enum +{ + Cc_Success = 0, /* channel configured successfully */ + Cc_InvalidChannelType = 1, /* invalid Channel Type */ + Cc_InvalidChannel = 2, /* invalid Channel A Id */ + Cc_ChannelActiveA = 3, /* Channel A is currently active */ + Cc_InvalidInputPortA = 4, /* invalid Input A Port */ + Cc_InvalidInputSlotA = 5, /* invalid Input A Slot */ + Cc_BusyInputSlotA = 6, /* busy Input A Slot */ + Cc_InvalidOutputPortA = 7, /* invalid Output A Port */ + Cc_InvalidOutputSlotA = 8, /* invalid Output A Slot */ + Cc_BusyOutputSlotA = 9, /* busy Output A Slot */ + Cc_InvalidInputPortB = 10, /* invalid Input B Port */ + Cc_InvalidInputSlotB = 11, /* invalid Input B Slot */ + Cc_BusyInputSlotB = 12, /* busy Input B Slot */ + Cc_InvalidPktInCodingA = 13, /* invalid Packet In A Coding */ + Cc_InvalidPktOutCodingA = 14, /* invalid Packet Out A Coding */ + Cc_InvalidPktInSizeA = 15, /* invalid Packet In A Frame Size */ + Cc_InvalidPktOutSizeA = 16, /* invalid Packet Out A Frame Size */ + + Cc_ChanTypeNotConfigured = 21, /* channel type was not configured */ + Cc_InsuffECResources = 22, /* insufficient ecan resources avail. */ + Cc_InsuffTDMResources = 23, /* insufficient tdm block resources avail. */ + + Cc_InsuffPktBufResources = 25, /* insufficient pkt buffer resources avail. */ + Cc_InsuffPcmBufResources = 26, /* insufficient pcm buffer resources avail. */ + + Cc_BadPcmEcNlpType = 30, /* invalid EC Nlp type */ + Cc_BadPcmEcTapLength = 31, /* invalid EC tap length */ + Cc_BadPcmEcDblTalkThresh = 32, /* invalid EC double-talk threshold */ + Cc_BadPcmEcNlpThreshold = 33, /* invalid EC Nlp threshold */ + Cc_BadPcmEcCngThreshold = 34, /* invalid EC Cng threshold */ + Cc_BadPcmEcAdaptLimit = 35, /* invalid EC Adapt Limit */ + Cc_BadPcmEcCrossCorrLim = 36, /* invalid EC Cross Correlation Limit */ + Cc_BadPcmEcNumFirSegs = 37, /* invalid EC Number of FirSegments */ + Cc_BadPcmEcFirSegLen = 38, /* invalid EC Fir Segment Length */ + + /*Cc_InvalidNumEcsEnabled = 48, */ /* more than 1 Ec enabled on channel */ + Cc_InvalidFrameRate = 49, /* invalid gpak frame rate */ + Cc_InvalidSoftCompand = 50, /* invalid softCompanding type */ + + Cc_InvalidMuteToneA = 51, /* invalid MuteToneA set, no detector */ + Cc_InvalidMuteToneB = 52, /* invalid MuteToneB set, no detector */ + Cc_InsuffFaxCngDetResources = 53 /* insufficient tdm block resources avail. */ + +} GPAK_ChannelConfigStat_t; + +/* Tear Down Channel reply status codes. */ +typedef enum +{ + Td_Success = 0, /* channel torn down successfully */ + Td_InvalidChannel = 1, /* invalid Channel Id */ + Td_ChannelNotActive = 2 /* channel is not active */ +} GPAK_TearDownChanStat_t; + + +typedef enum +{ + Ac_Success = 0, /* algorithm control is successfull */ + Ac_InvalidChannel = 1, /* invalid channel identifier */ + Ac_InvalidCode = 2, /* invalid algorithm control code */ + Ac_ECNotEnabled = 3, /* echo canceller was not allocated */ + Ac_InvalidSoftComp = 4, /* invalid softcompanding, 'cause serial port not in companding mode */ + Ac_InvalidDTMFMuteA = 5, /* A side invalid Mute, since no dtmf detector */ + Ac_InvalidDTMFMuteB = 6, /* B side invalid Mute, since no dtmf detector */ + Ac_InvalidFaxCngA = 7, /* A side FAXCNG detector not available */ + Ac_InvalidFaxCngB = 8, /* B side FAXCNG detector not available */ + Ac_InvalidSysConfig = 9 /* No new system parameters (DTMF config) wrriten yet */ +} GPAK_AlgControlStat_t; + +/* Write System Parameters reply status codes. */ +typedef enum +{ + Sp_Success = 0, /* System Parameters written successfully */ + Sp_BadTwistThresh = 29 /* invalid twist threshold */ + +} GPAK_SysParmsStat_t; + +#endif /* prevent multiple inclusion */ + + + + + + + + + + + + + + + + + + + diff -uNr zaptel-1.4.8/wcte12xp/.svn/text-base/GpakHpi.h.svn-base zaptel-1.4/wcte12xp/.svn/text-base/GpakHpi.h.svn-base --- zaptel-1.4.8/wcte12xp/.svn/text-base/GpakHpi.h.svn-base 1970-01-01 01:00:00.000000000 +0100 +++ zaptel-1.4/wcte12xp/.svn/text-base/GpakHpi.h.svn-base 2008-02-03 17:46:02.000000000 +0100 @@ -0,0 +1,80 @@ +/* + * Copyright (c) 2001, Adaptive Digital Technologies, Inc. + * + * File Name: GpakHpi.h + * + * Description: + * This file contains common definitions related to the G.PAK interface + * between a host processor and a DSP processor via the Host Port Interface. + * + * Version: 1.0 + * + * Revision History: + * 10/17/01 - Initial release. + * + * This program has been released under the terms of the GPL version 2 by + * permission of Adaptive Digital Technologies, Inc. The standard + * GPL disclaimer is given inline below for your convenience. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef _GPAKHPI_H /* prevent multiple inclusion */ +#define _GPAKHPI_H + + +/* Definition of G.PAK Command/Reply message type codes. */ +#define MSG_NULL_REPLY 0 /* Null Reply (unsupported Command) */ +#define MSG_SYS_CONFIG_RQST 1 /* System Configuration Request */ +#define MSG_SYS_CONFIG_REPLY 2 /* System Configuration Reply */ +#define MSG_READ_SYS_PARMS 3 /* Read System Parameters */ +#define MSG_READ_SYS_PARMS_REPLY 4 /* Read System Parameters Reply */ +#define MSG_WRITE_SYS_PARMS 5 /* Write System Parameters */ +#define MSG_WRITE_SYS_PARMS_REPLY 6 /* Write System Parameters Reply */ +#define MSG_CONFIGURE_PORTS 7 /* Configure Serial Ports */ +#define MSG_CONFIG_PORTS_REPLY 8 /* Configure Serial Ports Reply */ +#define MSG_CONFIGURE_CHANNEL 9 /* Configure Channel */ +#define MSG_CONFIG_CHAN_REPLY 10 /* Configure Channel Reply */ +#define MSG_TEAR_DOWN_CHANNEL 11 /* Tear Down Channel */ +#define MSG_TEAR_DOWN_REPLY 12 /* Tear Down Channel Reply */ +#define MSG_CHAN_STATUS_RQST 13 /* Channel Status Request */ +#define MSG_CHAN_STATUS_REPLY 14 /* Channel Status Reply */ + +#define MSG_TEST_MODE 17 /* Configure/Perform Test Mode */ +#define MSG_TEST_REPLY 18 /* Configure/Perform Test Mode Reply */ + +#define MSG_ALG_CONTROL 27 /* algorithm control */ +#define MSG_ALG_CONTROL_REPLY 28 /* algorithm control reply */ +#define MSG_GET_TXCID_ADDRESS 29 /* get tx cid buffer start address */ +#define MSG_GET_TXCID_ADDRESS_REPLY 30 /* get tx cid buffer start addr reply */ + +#define MSG_PING 35 /* ping command */ +#define MSG_PING_REPLY 36 /* ping command reply */ +#define MSG_SERIAL_TXVAL 37 /* transmit serial fixed value */ +#define MSG_SERIAL_TXVAL_REPLY 38 /* transmit serial fixed value reply */ +#define MSG_TDM_LOOPBACK 39 /* tdm loopback control */ +#define MSG_TDM_LOOPBACK_REPLY 40 /* tdm loopback control reply */ +#define MSG_RESET_USAGE_STATS 41 /* reset cpu usage stats */ +#define MSG_RESET_USAGE_STATS_REPLY 42 /* reset cpu usage stats reply */ + +#define MSG_RESET_FRAME_STATS 47 /* reset framing stats */ +#define MSG_RESET_FRAME_STATS_REPLY 48 /* reset framing stats reply */ + +#define MSG_READ_DSP_MEMORY 49 /* read small section of DSP's memory */ +#define MSG_READ_DSP_MEMORY_REPLY 50 /* read memory reply */ + +#define MSG_ACCESSGPIO 51 +#define MSG_ACCESSGPIO_REPLY 52 +#endif /* prevent multiple inclusion */ diff -uNr zaptel-1.4.8/wcte12xp/.svn/text-base/Kbuild.svn-base zaptel-1.4/wcte12xp/.svn/text-base/Kbuild.svn-base --- zaptel-1.4.8/wcte12xp/.svn/text-base/Kbuild.svn-base 1970-01-01 01:00:00.000000000 +0100 +++ zaptel-1.4/wcte12xp/.svn/text-base/Kbuild.svn-base 2008-02-03 17:46:02.000000000 +0100 @@ -0,0 +1,23 @@ +obj-m += wcte12xp.o + +EXTRA_CFLAGS := -I$(src)/.. -Wno-undef + +ifeq ($(HOTPLUG_FIRMWARE),yes) + EXTRA_CFLAGS+=-DHOTPLUG_FIRMWARE +endif + +wcte12xp-objs := base.o vpmadt032.o GpakApi.o + +ifneq ($(HOTPLUG_FIRMWARE),yes) +wcte12xp-objs += ../firmware/zaptel-fw-vpmadt032.o +endif + +$(obj)/../firmware/zaptel-fw-vpmadt032.o: $(obj)/base.o + $(MAKE) -C $(obj)/../firmware zaptel-fw-vpmadt032.o + +$(obj)/base.o: $(src)/vpmadt032.h $(src)/wcte12xp.h +$(obj)/base.o: $(src)/../zaptel.h + +$(obj)/vpmadt032.o: $(src)/vpmadt032.h + +$(obj)/GpakApi.o: $(src)/GpakApi.h diff -uNr zaptel-1.4.8/wcte12xp/.svn/text-base/Makefile.svn-base zaptel-1.4/wcte12xp/.svn/text-base/Makefile.svn-base --- zaptel-1.4.8/wcte12xp/.svn/text-base/Makefile.svn-base 1970-01-01 01:00:00.000000000 +0100 +++ zaptel-1.4/wcte12xp/.svn/text-base/Makefile.svn-base 2008-02-03 17:46:02.000000000 +0100 @@ -0,0 +1,25 @@ +ifneq ($(KBUILD_EXTMOD),) +# We only get here on kernels 2.6.0-2.6.9 . +# For newer kernels, Kbuild will be included directly by the kernel +# build system. +include $(src)/Kbuild + +else + +# building for 2.4 kernels means no VPM support, so none of the VPM support +# modules are included in the Makefile rules + +all: wcte12xp.o + +%.o: %.c + $(CC) $(KFLAGS) -o $@ -c $< + +base.o: ../zaptel.h + +wcte12xp.o: base.o + $(LD) -r -o $@ $^ + +clean: + rm -f *.o + +endif diff -uNr zaptel-1.4.8/wcte12xp/.svn/text-base/vpmadt032.c.svn-base zaptel-1.4/wcte12xp/.svn/text-base/vpmadt032.c.svn-base --- zaptel-1.4.8/wcte12xp/.svn/text-base/vpmadt032.c.svn-base 1970-01-01 01:00:00.000000000 +0100 +++ zaptel-1.4/wcte12xp/.svn/text-base/vpmadt032.c.svn-base 2008-02-03 17:46:02.000000000 +0100 @@ -0,0 +1,1385 @@ +/* + * Digium, Inc. Wildcard TE12xP T1/E1 card Driver + * + * Written by Michael Spiceland <mspiceland@digium.com> + * + * Adapted from the wctdm24xxp and wcte11xp drivers originally + * written by Mark Spencer <markster@digium.com> + * Matthew Fredrickson <creslin@digium.com> + * William Meadows <wmeadows@digium.com> + * + * Copyright (C) 2007, Digium, Inc. + * + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#include <linux/delay.h> +#include <asm/semaphore.h> +#include <linux/pci.h> +#include <linux/firmware.h> +#include <linux/list.h> + +#include "zaptel.h" + +#include "wcte12xp.h" +#include "vpmadt032.h" +#include "GpakApi.h" + +extern struct t1 *ifaces[WC_MAX_IFACES]; + +extern int vpmnlptype; +extern int vpmnlpthresh; +extern int vpmnlpmaxsupp; + +#ifdef VPM_SUPPORT + +inline void vpm150m_cmd_dequeue(struct t1 *wc, volatile unsigned char *writechunk, int whichframe) +{ + struct vpm150m_cmd *curcmd = NULL; + struct vpm150m *vpm150m = wc->vpm150m; + int x; + unsigned char leds = ~((wc->intcount / 1000) % 8) & 0x7; + + /* Skip audio */ + writechunk += 66; + + if (test_bit(VPM150M_SPIRESET, &vpm150m->control) || test_bit(VPM150M_HPIRESET, &vpm150m->control)) { + debug_printk(1, "HW Resetting VPMADT032 ...\n"); + for (x = 0; x < 4; x++) { + if (!x) { + if (test_and_clear_bit(VPM150M_SPIRESET, &vpm150m->control)) + writechunk[CMD_BYTE(x, 0, 1)] = 0x08; + else if (test_and_clear_bit(VPM150M_HPIRESET, &vpm150m->control)) + writechunk[CMD_BYTE(x, 0, 1)] = 0x0b; + } else + writechunk[CMD_BYTE(x, 0, 1)] = 0x00 | leds; + writechunk[CMD_BYTE(x, 1, 1)] = 0; + writechunk[CMD_BYTE(x, 2, 1)] = 0x00; + } + return; + } + + /* Search for something waiting to transmit */ + for (x = 0; x < VPM150M_MAX_COMMANDS; x++) { + if ((vpm150m->cmdq[x].flags & (__VPM150M_RD | __VPM150M_WR)) && + !(vpm150m->cmdq[x].flags & (__VPM150M_FIN | __VPM150M_TX))) { + curcmd = &vpm150m->cmdq[x]; + curcmd->ident = wc->txident; + curcmd->flags |= __VPM150M_TX; + break; + } + } + if (curcmd) { +#if 0 + printk("Found command txident = %d, desc = 0x%x, addr = 0x%x, data = 0x%x\n", curcmd->txident, curcmd->desc, curcmd->addr, curcmd->data); +#endif + if (curcmd->flags & __VPM150M_RWPAGE) { + /* Set CTRL access to page*/ + writechunk[CMD_BYTE(0, 0, 1)] = (0x8 << 4); + writechunk[CMD_BYTE(0, 1, 1)] = 0; + writechunk[CMD_BYTE(0, 2, 1)] = 0x20; + + /* Do a page write */ + if (curcmd->flags & __VPM150M_WR) + writechunk[CMD_BYTE(1, 0, 1)] = ((0x8 | 0x4) << 4); + else + writechunk[CMD_BYTE(1, 0, 1)] = ((0x8 | 0x4 | 0x1) << 4); + writechunk[CMD_BYTE(1, 1, 1)] = 0; + if (curcmd->flags & __VPM150M_WR) + writechunk[CMD_BYTE(1, 2, 1)] = curcmd->data[0] & 0xf; + else + writechunk[CMD_BYTE(1, 2, 1)] = 0; + + if (curcmd->flags & __VPM150M_WR) { + /* Fill in buffer to size */ + writechunk[CMD_BYTE(2, 0, 1)] = 0; + writechunk[CMD_BYTE(2, 1, 1)] = 0; + writechunk[CMD_BYTE(2, 2, 1)] = 0; + } else { + /* Do reads twice b/c of vpmadt032 bug */ + writechunk[CMD_BYTE(2, 0, 1)] = ((0x8 | 0x4 | 0x1) << 4); + writechunk[CMD_BYTE(2, 1, 1)] = 0; + writechunk[CMD_BYTE(2, 2, 1)] = 0; + } + + /* Clear XADD */ + writechunk[CMD_BYTE(3, 0, 1)] = (0x8 << 4); + writechunk[CMD_BYTE(3, 1, 1)] = 0; + writechunk[CMD_BYTE(3, 2, 1)] = 0; + + /* Fill in buffer to size */ + writechunk[CMD_BYTE(4, 0, 1)] = 0; + writechunk[CMD_BYTE(4, 1, 1)] = 0; + writechunk[CMD_BYTE(4, 2, 1)] = 0; + + } else { + /* Set address */ + writechunk[CMD_BYTE(0, 0, 1)] = ((0x8 | 0x4) << 4); + writechunk[CMD_BYTE(0, 1, 1)] = (curcmd->address >> 8) & 0xff; + writechunk[CMD_BYTE(0, 2, 1)] = curcmd->address & 0xff; + + /* Send/Get our data */ + if (curcmd->flags & __VPM150M_WR) { + if (curcmd->datalen > 1) + writechunk[CMD_BYTE(1, 0, 1)] = ((0x8 | (0x1 << 1)) << 4); + else + writechunk[CMD_BYTE(1, 0, 1)] = ((0x8 | (0x3 << 1)) << 4); + } else + if (curcmd->datalen > 1) + writechunk[CMD_BYTE(1, 0, 1)] = ((0x8 | (0x1 << 1) | 0x1) << 4); + else + writechunk[CMD_BYTE(1, 0, 1)] = ((0x8 | (0x3 << 1) | 0x1) << 4); + writechunk[CMD_BYTE(1, 1, 1)] = (curcmd->data[0] >> 8) & 0xff; + writechunk[CMD_BYTE(1, 2, 1)] = curcmd->data[0] & 0xff; + + if (curcmd->flags & __VPM150M_WR) { + /* Fill in */ + writechunk[CMD_BYTE(2, 0, 1)] = 0; + writechunk[CMD_BYTE(2, 1, 1)] = 0; + writechunk[CMD_BYTE(2, 2, 1)] = 0; + } else { + /* Do this again for reads b/c of the bug in vpmadt032 */ + writechunk[CMD_BYTE(2, 0, 1)] = ((0x8 | (0x3 << 1) | 0x1) << 4); + writechunk[CMD_BYTE(2, 1, 1)] = (curcmd->data[0] >> 8) & 0xff; + writechunk[CMD_BYTE(2, 2, 1)] = curcmd->data[0] & 0xff; + } + + if (curcmd->datalen > 1) { + if (curcmd->flags & __VPM150M_WR) + writechunk[CMD_BYTE(3, 0, 1)] = ((0x8 | (0x1 << 1)) << 4); + else + writechunk[CMD_BYTE(3, 0, 1)] = ((0x8 | (0x1 << 1) | 0x1) << 4); + writechunk[CMD_BYTE(3, 1, 1)] = (curcmd->data[1] >> 8) & 0xff; + writechunk[CMD_BYTE(3, 2, 1)] = curcmd->data[1] & 0xff; + } else { + /* Fill in the rest */ + writechunk[CMD_BYTE(3, 0, 1)] = 0; + writechunk[CMD_BYTE(3, 1, 1)] = 0; + writechunk[CMD_BYTE(3, 2, 1)] = 0; + } + + if (curcmd->datalen > 2) { + if (curcmd->flags & __VPM150M_WR) + writechunk[CMD_BYTE(4, 0, 1)] = ((0x8 | (0x1 << 1)) << 4); + else + writechunk[CMD_BYTE(4, 0, 1)] = ((0x8 | (0x1 << 1) | 0x1) << 4); + writechunk[CMD_BYTE(4, 1, 1)] = (curcmd->data[2] >> 8) & 0xff; + writechunk[CMD_BYTE(4, 2, 1)] = curcmd->data[2] & 0xff; + } else { + /* Fill in the rest */ + writechunk[CMD_BYTE(4, 0, 1)] = 0; + writechunk[CMD_BYTE(4, 1, 1)] = 0; + writechunk[CMD_BYTE(4, 2, 1)] = 0; + } + } + } else if (test_and_clear_bit(VPM150M_SWRESET, &vpm150m->control)) { + debug_printk(1, "Booting VPMADT032\n"); + for (x = 0; x < 7; x++) { + if (x == 0) + writechunk[CMD_BYTE(x, 0, 1)] = (0x8 << 4); + else + writechunk[CMD_BYTE(x, 0, 1)] = 0x00; + writechunk[CMD_BYTE(x, 1, 1)] = 0; + if (x == 0) + writechunk[CMD_BYTE(x, 2, 1)] = 0x01; + else + writechunk[CMD_BYTE(x, 2, 1)] = 0x00; + } + } else { + for (x = 0; x < 7; x++) { + writechunk[CMD_BYTE(x, 0, 1)] = 0x00; + writechunk[CMD_BYTE(x, 1, 1)] = 0x00; + writechunk[CMD_BYTE(x, 2, 1)] = 0x00; + } + } + + /* Add our leds in */ + for (x = 0; x < 7; x++) + writechunk[CMD_BYTE(x, 0, 1)] |= leds; + +#if 0 + int y; + for (x = 0; x < 7; x++) { + for (y = 0; y < 3; y++) { + if (writechunk[CMD_BYTE(x, y, 1)] & 0x2) { + module_printk("the test bit is high for byte %d\n", y); + } + } + } +#endif + + /* Now let's figure out if we need to check for DTMF */ + /* polling */ + if (test_bit(VPM150M_ACTIVE, &vpm150m->control) && !whichframe && !(wc->intcount % 100)) + queue_work(vpm150m->wq, &vpm150m->work_dtmf); + +#if 0 + /* This may be needed sometime in the future to troubleshoot ADT related issues. */ + if (test_bit(VPM150M_ACTIVE, &vpm150m->control) && !whichframe && !(wc->intcount % 10000)) + queue_work(vpm150m->wq, &vpm150m->work_debug); +#endif +} + +inline void vpm150m_cmd_decipher(struct t1 *wc, volatile unsigned char *readchunk) +{ + unsigned char ident; + int x, i; + + /* Skip audio */ + readchunk += 66; + /* Search for any pending results */ + for (x = 0; x < VPM150M_MAX_COMMANDS; x++) { + if ((wc->vpm150m->cmdq[x].flags & (__VPM150M_RD | __VPM150M_WR)) && + (wc->vpm150m->cmdq[x].flags & (__VPM150M_TX)) && + !(wc->vpm150m->cmdq[x].flags & (__VPM150M_FIN))) { + ident = wc->vpm150m->cmdq[x].ident; + if (ident == wc->rxident) { + /* Store result */ + for (i = 0; i < wc->vpm150m->cmdq[x].datalen; i++) { + wc->vpm150m->cmdq[x].data[i] = (0xff & readchunk[CMD_BYTE((2 + i), 1, 1)]) << 8; + wc->vpm150m->cmdq[x].data[i] |= readchunk[CMD_BYTE((2 + i), 2, 1)]; + } + if (wc->vpm150m->cmdq[x].flags & __VPM150M_WR) { + /* Go ahead and clear out writes since they need no acknowledgement */ + wc->vpm150m->cmdq[x].flags = 0; + } else + wc->vpm150m->cmdq[x].flags |= __VPM150M_FIN; + break; + } + } + } +} + +static inline struct t1 * wc_find_iface(unsigned short dspid) +{ + int i; + struct t1 *ret = NULL; + unsigned long flags; + + spin_lock_irqsave(&ifacelock, flags); + for (i = 0; i < WC_MAX_IFACES; i++) + if (ifaces[i] && ifaces[i]->vpm150m && (ifaces[i]->vpm150m->dspid == dspid)) + ret = ifaces[i]; + spin_unlock_irqrestore(&ifacelock, flags); + + return ret; +} + +static struct vpm150m_cmd * vpm150m_empty_slot(struct t1 *wc) +{ + unsigned int x; + + for (x = 0; x < VPM150M_MAX_COMMANDS; x++) { + if (!wc->vpm150m->cmdq[x].flags) { + return &wc->vpm150m->cmdq[x]; + } + } + return NULL; +} + +/* Wait for any outstanding commands to be completed. */ +static inline int vpm150m_io_wait(struct t1 *wc) +{ + int x; + int ret=0; + for (x=0; x < VPM150M_MAX_COMMANDS;) { + if (wc->vpm150m->cmdq[x].flags) { + if ((ret=schluffen(&wc->regq))) { + return ret; + } + x=0; + } + else { + ++x; + } + } + return ret; +} + +int t1_vpm150m_getreg_full_async(struct t1 *wc, int pagechange, unsigned int len, + unsigned short addr, unsigned short *outbuf, struct vpm150m_cmd **hit_p) +{ + int ret=0; + unsigned long flags; + BUG_ON(!hit_p); + spin_lock_irqsave(&wc->reglock, flags); + (*hit_p) = vpm150m_empty_slot(wc); + if (*hit_p) { + (*hit_p)->flags = __VPM150M_RD; + if (pagechange) { + (*hit_p)->flags |= __VPM150M_RWPAGE; + } + (*hit_p)->datalen = len; + (*hit_p)->address = addr; + memset((*hit_p)->data, 0, len*sizeof(outbuf[0])); + } + else { + ret = -EBUSY; + } + spin_unlock_irqrestore(&wc->reglock, flags); + return ret; +} + +int t1_vpm150m_getreg_full_return(struct t1 *wc, int pagechange, unsigned int len, + unsigned short addr, unsigned short *outbuf, struct vpm150m_cmd **hit_p) +{ + int ret = 0; + unsigned long flags; + BUG_ON(!hit_p); + spin_lock_irqsave(&wc->reglock, flags); + do { + if ((*hit_p)->flags & __VPM150M_FIN) { + memcpy(outbuf, (*hit_p)->data, len*(sizeof(outbuf[0]))); + (*hit_p)->flags = 0; + (*hit_p) = NULL; + ret = 0; + } + else { + spin_unlock_irqrestore(&wc->reglock, flags); + if ((ret=schluffen(&wc->regq))) { + return ret; + } + spin_lock_irqsave(&wc->reglock, flags); + ret = -EBUSY; + } + } while (-EBUSY == ret); + spin_unlock_irqrestore(&wc->reglock, flags); + return ret; +} + +int t1_vpm150m_getreg_full(struct t1 *wc, int pagechange, unsigned int len, unsigned short addr, unsigned short *outbuf) +{ + struct vpm150m_cmd *hit = 0; + int ret = 0; + do { + ret = t1_vpm150m_getreg_full_async(wc, pagechange, len, addr, outbuf, &hit); + if (!hit) { + if ( -EBUSY == ret ) { + if ((ret = schluffen(&wc->regq))) + return ret; + } + BUG_ON( 0 != ret); + } + } while (!hit); + + ret = t1_vpm150m_getreg_full_return(wc, pagechange, len, addr, outbuf, &hit); + return ret; +} + +int t1_vpm150m_setreg_full(struct t1 *wc, int pagechange, unsigned int len, unsigned int addr, unsigned short *data) +{ + unsigned long flags; + struct vpm150m_cmd *hit; + int ret, i; + do { + spin_lock_irqsave(&wc->reglock, flags); + hit = vpm150m_empty_slot(wc); + if (hit) { + hit->flags = __VPM150M_WR; + if (pagechange) + hit->flags |= __VPM150M_RWPAGE; + hit->address = addr; + hit->datalen = len; + for (i = 0; i < len; i++) + hit->data[i] = data[i]; + } + spin_unlock_irqrestore(&wc->reglock, flags); + if (!hit) { + if ((ret = schluffen(&wc->regq))) + return ret; + } + } while (!hit); + return (hit) ? 0 : -1; +} + +int t1_vpm150m_setpage(struct t1 *wc, unsigned short addr) +{ + addr &= 0xf; + /* Let's optimize this a little bit */ + if (wc->vpm150m->curpage == addr) + return 0; + else { + wc->vpm150m->curpage = addr; + } + + return t1_vpm150m_setreg_full(wc, 1, 1, 0, &addr); +} + +unsigned char t1_vpm150m_getpage(struct t1 *wc) +{ + unsigned short res; + t1_vpm150m_getreg_full(wc, 1, 1, 0, &res); + return res; +} + +int t1_vpm150m_setreg(struct t1 *wc, unsigned int len, unsigned int addr, unsigned short *data) +{ + int res; + t1_vpm150m_setpage(wc, addr >> 16); + if ((addr >> 16) != ((addr + len) >> 16)) + module_printk("setreg: You found it!\n"); + res = t1_vpm150m_setreg_full(wc, 0, len, addr & 0xffff, data); + return res; +} + +unsigned short t1_vpm150m_getreg(struct t1 *wc, unsigned int len, unsigned int addr, unsigned short *data) +{ + unsigned short res; + t1_vpm150m_setpage(wc, addr >> 16); + if ((addr >> 16) != ((addr + len) >> 16)) + module_printk("getreg: You found it!\n"); + res = t1_vpm150m_getreg_full(wc, 0, len, addr & 0xffff, data); + return res; +} + +static char vpm150mtone_to_zaptone(GpakToneCodes_t tone) +{ + switch (tone) { + case DtmfDigit0: + return '0'; + case DtmfDigit1: + return '1'; + case DtmfDigit2: + return '2'; + case DtmfDigit3: + return '3'; + case DtmfDigit4: + return '4'; + case DtmfDigit5: + return '5'; + case DtmfDigit6: + return '6'; + case DtmfDigit7: + return '7'; + case DtmfDigit8: + return '8'; + case DtmfDigit9: + return '9'; + case DtmfDigitPnd: + return '#'; + case DtmfDigitSt: + return '*'; + case DtmfDigitA: + return 'A'; + case DtmfDigitB: + return 'B'; + case DtmfDigitC: + return 'C'; + case DtmfDigitD: + return 'D'; + case EndofCngDigit: + return 'f'; + default: + return 0; + } +} + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20) +static void vpm150m_echocan_bh(void *data) +{ + struct vpm150m *vpm150m = data; +#else +static void vpm150m_echocan_bh(struct work_struct *data) +{ + struct vpm150m *vpm150m = container_of(data, struct vpm150m, work_echocan); +#endif + struct t1 *wc = vpm150m->wc; + struct list_head *task; + struct list_head *next_task; + unsigned long flags; + + list_for_each_safe(task, next_task, &vpm150m->worklist) { + struct vpm150m_workentry *we = list_entry(task, struct vpm150m_workentry, list); + struct zt_chan *chan = we->chan; + int deflaw; + int res; + GPAK_AlgControlStat_t pstatus; + + if (we->params.tap_length) { + /* configure channel for the ulaw/alaw */ + unsigned int start = wc->intcount; + + if (memcmp(&we->params, &vpm150m->chan_params[chan->chanpos - 1], sizeof(we->params))) { + /* set parameters */ + vpm150m->chan_params[chan->chanpos - 1] = we->params; + } + + deflaw = chan->span->deflaw; + debug_printk(1, "Enabling EC on channel %d (law %d)\n", chan->chanpos, deflaw); + if (deflaw == 2) /* alaw */ + res = gpakAlgControl(vpm150m->dspid, chan->chanpos - 1, EnableALawSwCompanding, &pstatus); + else if (deflaw == 1) /* alaw */ + res = gpakAlgControl(vpm150m->dspid, chan->chanpos - 1, EnableMuLawSwCompanding, &pstatus); + else { + module_printk("Undefined law for channel %d.\n", chan->chanpos); + res = -1; + } + + if (res) { + module_printk("Unable to set SW Companding on channel %d (reason %d)\n", chan->chanpos, res); + } + + res = gpakAlgControl(vpm150m->dspid, chan->chanpos - 1, EnableEcanA, &pstatus); + debug_printk(2, "Echo can enable took %d ms\n", wc->intcount - start); + } else { + unsigned int start = wc->intcount; + debug_printk(1, "Disabling EC on channel %d\n", chan->chanpos); + res = gpakAlgControl(vpm150m->dspid, chan->chanpos - 1, BypassSwCompanding, &pstatus); + if (res) + module_printk("Unable to disable sw companding on echo cancellation channel %d (reason %d)\n", chan->chanpos, res); + res = gpakAlgControl(vpm150m->dspid, chan->chanpos - 1, BypassEcanA, &pstatus); + if (res) + module_printk("Unable to disable echo can on channel %d (reason %d)\n", chan->chanpos, res); + debug_printk(2, "Echocan disable took %d ms\n", wc->intcount - start); + } + if (res) { + module_printk("Unable to toggle echo cancellation on channel %d (reason %d)\n", chan->chanpos, res); + } + + spin_lock_irqsave(&vpm150m->lock, flags); + list_del(task); + spin_unlock_irqrestore(&vpm150m->lock, flags); + kfree(we); + } +} + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20) +static void vpm150m_debug_bh(void *data) +{ + struct vpm150m *vpm150m = data; +#else +static void vpm150m_debug_bh(struct work_struct *data) +{ + struct vpm150m *vpm150m = container_of(data, struct vpm150m, work_debug); +#endif + unsigned short int FrammingError1Count, FramingError2Count, FramingError3Count, + DmaStopErrorCount, DmaSlipStatsBuffer; + + if (gpakReadFramingStats(vpm150m->dspid, &FrammingError1Count, &FramingError2Count, &FramingError3Count, + &DmaStopErrorCount, &DmaSlipStatsBuffer)) + { + module_printk("There was an error getting framing stats.\n"); + } + if (FrammingError1Count||FramingError2Count||FramingError3Count||DmaStopErrorCount||DmaSlipStatsBuffer) + { + module_printk("FramingStats Error: %d %d %d %d %d\n", + FrammingError1Count, FramingError2Count, FramingError3Count, DmaStopErrorCount, DmaSlipStatsBuffer); + } +} + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20) +static void vpm150m_dtmf_bh(void *data) +{ + struct vpm150m *vpm150m = data; +#else +static void vpm150m_dtmf_bh(struct work_struct *data) +{ + struct vpm150m *vpm150m = container_of(data, struct vpm150m, work_dtmf); +#endif + struct t1 *wc = vpm150m->wc; + int i; + + for (i = 0; i < wc->span.channels; i++) { + int enable = -1; + if (test_bit(i, &vpm150m->desireddtmfmutestate)) { + if (!test_bit(i, &vpm150m->curdtmfmutestate)) { + enable = 1; + } + } else { + if (test_bit(i, &vpm150m->curdtmfmutestate)) { + enable = 0; + } + } + if (enable > -1) { + unsigned int start = wc->intcount; + GPAK_AlgControlStat_t pstatus; + int res; + + if (enable) { + res = gpakAlgControl(vpm150m->dspid, i, EnableDTMFMuteA, &pstatus); + debug_printk(2, "DTMF mute enable took %d ms\n", wc->intcount - start); + } else { + res = gpakAlgControl(vpm150m->dspid, i, DisableDTMFMuteA, &pstatus); + debug_printk(2, "DTMF mute disable took %d ms\n", wc->intcount - start); + } + if (!res) + change_bit(i, &vpm150m->curdtmfmutestate); + } + } + + if (test_bit(VPM150M_DTMFDETECT, &vpm150m->control)) { + unsigned short channel; + GpakAsyncEventCode_t eventcode; + GpakAsyncEventData_t eventdata; + gpakReadEventFIFOMessageStat_t res; + unsigned int start = wc->intcount; + + do { + res = gpakReadEventFIFOMessage(vpm150m->dspid, &channel, &eventcode, &eventdata); + debug_printk(3, "ReadEventFIFOMessage took %d ms\n", wc->intcount - start); + + if (res == RefInvalidEvent || res == RefDspCommFailure) { + module_printk("Uh oh (%d)\n", res); + continue; + } + + if (eventcode == EventToneDetect) { + GpakToneCodes_t tone = eventdata.toneEvent.ToneCode; + int duration = eventdata.toneEvent.ToneDuration; + char zaptone = vpm150mtone_to_zaptone(tone); + + debug_printk(1, "Channel %d: Detected DTMF tone %d of duration %d\n", channel + 1, tone, duration); + + if (test_bit(channel, &wc->dtmfmask) && (eventdata.toneEvent.ToneDuration > 0)) { + struct zt_chan *chan = &wc->chans[channel]; + + module_printk("DTMF detected channel=%d tone=%d duration=%d\n", channel + 1, tone, duration); + + if ((tone != EndofMFDigit) && (zaptone != 0)) { + vpm150m->curtone[channel] = tone; + + if (test_bit(channel, &vpm150m->curdtmfmutestate)) { + unsigned long flags; + int y; + + /* Mute the audio data buffers */ + spin_lock_irqsave(&chan->lock, flags); + for (y = 0; y < chan->numbufs; y++) { + if ((chan->inreadbuf > -1) && (chan->readidx[y])) + memset(chan->readbuf[chan->inreadbuf], ZT_XLAW(0, chan), chan->readidx[y]); + } + spin_unlock_irqrestore(&chan->lock, flags); + } + if (!test_bit(channel, &wc->dtmfactive)) { + debug_printk(1,"Queuing DTMFDOWN %c\n", zaptone); + set_bit(channel, &wc->dtmfactive); + zt_qevent_lock(chan, (ZT_EVENT_DTMFDOWN | zaptone)); + } + } else if ((tone == EndofMFDigit) && test_bit(channel, &wc->dtmfactive)) { + debug_printk(1,"Queuing DTMFUP %c\n", vpm150mtone_to_zaptone(vpm150m->curtone[channel])); + zt_qevent_lock(chan, (ZT_EVENT_DTMFUP | vpm150mtone_to_zaptone(vpm150m->curtone[channel]))); + clear_bit(channel, &wc->dtmfactive); + } + } + } + } while ((res == RefEventAvail)); + } + + return; +} + +void t1_vpm150m_init(struct t1 *wc) { + struct vpm150m *vpm150m; + unsigned short i; + unsigned short reg; + unsigned long flags; + gpakPingDspStat_t pingstatus; + gpakDownloadStatus_t downloadstatus; + struct t1_firmware fw; + struct firmware embedded_firmware; + const struct firmware *firmware = &embedded_firmware; +#if !defined(HOTPLUG_FIRMWARE) + extern void _binary_zaptel_fw_vpmadt032_bin_size; + extern u8 _binary_zaptel_fw_vpmadt032_bin_start[]; +#else + static const char vpmadt032_firmware[] = "zaptel-fw-vpmadt032.bin"; +#endif + +#if 0 + unsigned short omsg[4] = { 0xdead, 0xbeef, 0x1111, 0x2222}; + unsigned short imsg[4]; +#endif + + if (!vpmsupport) { + module_printk("VPM Support Disabled\n"); + wc->vpm150m = NULL; + return; + } + + vpm150m = kmalloc(sizeof(struct vpm150m), GFP_KERNEL); + + if (!vpm150m) { + module_printk("Unable to allocate VPMADT032!\n"); + return; + } + memset(vpm150m, 0, sizeof(struct vpm150m)); + + /* Init our vpm150m struct */ + sema_init(&vpm150m->sem, 1); + vpm150m->curpage = 0x80; + + for (i = 0; i < sizeof(ifaces) / sizeof(ifaces[0]); i++) { + if (ifaces[i] == wc) + vpm150m->dspid = i; + } + + debug_printk(1, "Setting VPMADT032 DSP ID to %d\n", vpm150m->dspid); + spin_lock_irqsave(&wc->reglock, flags); + wc->vpm150m = vpm150m; + spin_unlock_irqrestore(&wc->reglock, flags); + + for (i = 0; i < 10; i++) + schluffen(&wc->regq); + + debug_printk(1, "Looking for VPMADT032 by testing page access: "); + for (i = 0; i < 0xf; i++) { + int x; + for (x = 0; x < 3; x++) { + t1_vpm150m_setpage(wc, i); + reg = t1_vpm150m_getpage(wc); + if (reg != i) { + /* If they have debug turned on we want them to be able to + * report where in the code the module failed to come up. */ + debug_printk(1, "Either no VPMADT032 module present or the module failed VPM page access test (%x != %x)\n", i, reg); + goto failed_exit; + } + } + } + debug_printk(1, "Passed\n"); + + set_bit(VPM150M_HPIRESET, &vpm150m->control); + msleep(2000); + + /* Set us up to page 0 */ + t1_vpm150m_setpage(wc, 0); + debug_printk(1, "VPMADT032 now doing address test: "); + for (i = 0; i < 16; i++) { + int x; + for (x = 0; x < 2; x++) { + t1_vpm150m_setreg(wc, 1, 0x1000, &i); + t1_vpm150m_getreg(wc, 1, 0x1000, ®); + if (reg != i) { + module_printk("VPMADT032 Failed address test: sent %x != %x on try %d\n", i, reg, x); + goto failed_exit; + } + } + } + debug_printk(1, "Passed\n"); + +#if 0 + /* begin short test */ +#define TEST_SIZE 1 + { + int i; + unsigned short msg[TEST_SIZE]; + + set_bit(VPM150M_HPIRESET, &vpm150m->control); + msleep(2000); + + /* lets see whats in there to start with*/ + gpakReadDspMemory(vpm150m->dspid, 0x1000, TEST_SIZE, msg); + printk("at first :"); + for (i = 0; i< TEST_SIZE; i++) + printk("%04x ", msg[i]); + printk("\n"); + + /* what if we put dead in there*/ + for (i = 0; i< TEST_SIZE; i++) + msg[i] = 0xdead; + gpakWriteDspMemory(vpm150m->dspid, 0x1000, TEST_SIZE, msg); + gpakReadDspMemory(vpm150m->dspid, 0x1000, TEST_SIZE, msg); + printk("now :"); + for (i = 0; i< TEST_SIZE; i++) + printk("%04x ", msg[i]); + printk("\n"); + + /* lets see if its in there now */ + gpakReadDspMemory(vpm150m->dspid, 0x1000, TEST_SIZE, msg); + printk("try again:"); + for (i = 0; i< TEST_SIZE; i++) + printk("%04x ", msg[i]); + printk("\n"); + } + + goto failed_exit; +#endif + +#define TEST_SIZE 2 + if (debug) { + int i; + unsigned short msg[TEST_SIZE]; + + set_bit(VPM150M_HPIRESET, &vpm150m->control); + msleep(2000); + gpakReadDspMemory(vpm150m->dspid, 0x1000, TEST_SIZE, msg); + for (i = 0; i< TEST_SIZE; i++) + printk("%x ", msg[i]); + printk("\n"); + for (i = 0; i< TEST_SIZE; i++) + msg[i] = 0xdead; + gpakWriteDspMemory(vpm150m->dspid, 0x1000, TEST_SIZE, msg); + gpakWriteDspMemory(vpm150m->dspid, 0x1000, TEST_SIZE, msg); + gpakReadDspMemory(vpm150m->dspid, 0x1000, TEST_SIZE, msg); + for (i = 0; i< TEST_SIZE; i++) + printk("%x ", msg[i]); + printk("\n"); + gpakReadDspMemory(vpm150m->dspid, 0x1000, TEST_SIZE, msg); + for (i = 0; i< TEST_SIZE; i++) + printk("%x ", msg[i]); + printk("\n"); + for (i = 0; i< TEST_SIZE; i++) + msg[i] = 0xbeef; + gpakWriteDspMemory(vpm150m->dspid, 0x1000, TEST_SIZE, msg); + gpakReadDspMemory(vpm150m->dspid, 0x1000, TEST_SIZE, msg); + for (i = 0; i< TEST_SIZE; i++) + printk("%x ", msg[i]); + printk("\n"); + gpakReadDspMemory(vpm150m->dspid, 0x1000, TEST_SIZE, msg); + for (i = 0; i< TEST_SIZE; i++) + printk("%x ", msg[i]); + printk("\n"); + for (i = 0; i< TEST_SIZE; i++) + msg[i] = 0x1111; + gpakWriteDspMemory(vpm150m->dspid, 0x1000, TEST_SIZE, msg); + gpakReadDspMemory(vpm150m->dspid, 0x1000, TEST_SIZE, msg); + for (i = 0; i< TEST_SIZE; i++) + printk("%x ", msg[i]); + printk("\n"); + gpakReadDspMemory(vpm150m->dspid, 0x1000, TEST_SIZE, msg); + for (i = 0; i< TEST_SIZE; i++) + printk("%x ", msg[i]); + printk("\n"); + for (i = 0; i< TEST_SIZE; i++) + msg[i] = 0x2222; + gpakWriteDspMemory(vpm150m->dspid, 0x1000, TEST_SIZE, msg); + gpakReadDspMemory(vpm150m->dspid, 0x1000, TEST_SIZE, msg); + for (i = 0; i< TEST_SIZE; i++) + printk("%x ", msg[i]); + printk("\n"); + gpakReadDspMemory(vpm150m->dspid, 0x1000, TEST_SIZE, msg); + for (i = 0; i< TEST_SIZE; i++) + printk("%x ", msg[i]); + printk("\n"); + } +#if 0 + printk("Sending\n"); + + for (i = 0; i < 4; i++) { + unsigned short x = 0xffff; + t1_vpm150m_setreg(wc, 1, 0x1000 + i, &x); + } + + gpakReadDspMemory(vpm150m->dspid, 0x1000, 4, imsg); + + printk("Read back:\n"); + for (i = 0; i < 4; i++) + printk("%x ", imsg[i]); + printk("\n"); + + printk("Sending\n"); + gpakWriteDspMemory(vpm150m->dspid, 0x1000, 4, omsg); + for (i = 0; i < 4; i++) + t1_vpm150m_getreg(wc, 1, 0x1000 + i, &imsg[i]); + + printk("Read back\n"); + for (i = 0; i < 4; i++) + printk("%x ", imsg[i]); + printk("\n"); + +#endif + +#if 0 + /* Load the firmware */ + set_bit(VPM150M_SPIRESET, &vpm150m->control); + + /* Wait for it to boot */ + msleep(7000); + + pingstatus = gpakPingDsp(vpm150m->dspid, &version); + + if (pingstatus) { + module_printk("Pingstatus %d, you failed!!! Ha ha ha ha\n", pingstatus); + } else + module_printk("version is 0x%08x\n", version); + + if (pingstatus || (version != 0x106)) { +#endif +#if defined(HOTPLUG_FIRMWARE) + if ((request_firmware(&firmware, vpmadt032_firmware, &wc->dev->dev) != 0) || + !firmware) { + printk("VPMADT032: firmware %s not available from userspace\n", vpmadt032_firmware); + goto failed_exit; + } +#else + embedded_firmware.data = _binary_zaptel_fw_vpmadt032_bin_start; + embedded_firmware.size = (size_t) &_binary_zaptel_fw_vpmadt032_bin_size; +#endif + fw.fw = firmware; + fw.offset = 0; + + set_bit(VPM150M_HPIRESET, &vpm150m->control); + + while (test_bit(VPM150M_HPIRESET, &vpm150m->control)) + schluffen(&wc->regq); + + module_printk("VPMADT032 Loading firwmare... "); + downloadstatus = gpakDownloadDsp(vpm150m->dspid, &fw); + + if (firmware != &embedded_firmware) + release_firmware(firmware); + + if (downloadstatus != 0) { + module_printk("Unable to download firmware to VPMADT032 with cause %d\n", downloadstatus); + goto failed_exit; + } else { + module_printk("Success\n"); + } + + set_bit(VPM150M_SWRESET, &vpm150m->control); + + while (test_bit(VPM150M_SWRESET, &vpm150m->control)) + schluffen(&wc->regq); + + msleep(700); +#if 0 + } +#endif + + pingstatus = gpakPingDsp(vpm150m->dspid, &vpm150m->version); + + if (!pingstatus) { + debug_printk(1, "Version of DSP is %x\n", vpm150m->version); + } else { + module_printk("Unable to ping the DSP (%d)!\n", pingstatus); + goto failed_exit; + } + + /* workqueue for DTMF and wc->span functions that cannot sleep */ + spin_lock_init(&vpm150m->lock); + vpm150m->wq = create_singlethread_workqueue("wcte12xp"); + vpm150m->wc = wc; + if (!vpm150m->wq) { + module_printk("Unable to create work queue!\n"); + goto failed_exit; + } +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20) + INIT_WORK(&vpm150m->work_echocan, vpm150m_echocan_bh, vpm150m); + INIT_WORK(&vpm150m->work_dtmf, vpm150m_dtmf_bh, vpm150m); + INIT_WORK(&vpm150m->work_debug, vpm150m_debug_bh, vpm150m); +#else + INIT_WORK(&vpm150m->work_echocan, vpm150m_echocan_bh); + INIT_WORK(&vpm150m->work_dtmf, vpm150m_dtmf_bh); + INIT_WORK(&vpm150m->work_debug, vpm150m_debug_bh); +#endif + INIT_LIST_HEAD(&wc->vpm150m->worklist); /* list of echocan tasks */ + + if (vpm150m_config_hw(wc)) { + goto failed_exit; + } + + return; + +failed_exit: + if (vpm150m->wq) { + destroy_workqueue(vpm150m->wq); + } + spin_lock_irqsave(&wc->reglock, flags); + wc->vpm150m = NULL; + spin_unlock_irqrestore(&wc->reglock, flags); + kfree(vpm150m); + + return; +} + +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + * gpakReadDspMemory - Read DSP memory. + * + * FUNCTION + * This function reads a contiguous block of words from DSP memory starting at + * the specified address. + * + * RETURNS + * nothing + * + */ +void gpakReadDspMemory( + unsigned short int DspId, /* DSP Identifier (0 to MAX_DSP_CORES-1) */ + DSP_ADDRESS DspAddress, /* DSP's memory address of first word */ + unsigned int NumWords, /* number of contiguous words to read */ + DSP_WORD *pWordValues /* pointer to array of word values variable */ + ) +{ + struct t1 *wc = wc_find_iface(DspId); + int i; + int transcount; + int ret; + + vpm150m_io_wait(wc); + if ( NumWords < VPM150M_MAX_COMMANDS ) { + struct vpm150m_cmd* cmds[VPM150M_MAX_COMMANDS] = {0}; + t1_vpm150m_setpage(wc, DspAddress >> 16); + DspAddress &= 0xffff; + for (i=0; i < NumWords; ++i) { + ret = t1_vpm150m_getreg_full_async(wc,0,1,DspAddress+i,&pWordValues[i], + &cmds[i]); + if (0 != ret) { + return; + } + } + for (i=NumWords-1; i >=0; --i) { + ret = t1_vpm150m_getreg_full_return(wc,0,1,DspAddress+i,&pWordValues[i], + &cmds[i]); + if (0 != ret) { + return; + } + } + } + else { + for (i = 0; i < NumWords;) { + if ((NumWords - i) > VPM150M_MAX_DATA) + transcount = VPM150M_MAX_DATA; + else + transcount = NumWords - i; + t1_vpm150m_getreg(wc, transcount, DspAddress + i, &pWordValues[i]); + i += transcount; + } + } + return; +} + + +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + * gpakWriteDspMemory - Write DSP memory. + * + * FUNCTION + * This function writes a contiguous block of words to DSP memory starting at + * the specified address. + * + * RETURNS + * nothing + * + */ +void gpakWriteDspMemory( + unsigned short int DspId, /* DSP Identifier (0 to MAX_DSP_CORES-1) */ + DSP_ADDRESS DspAddress, /* DSP's memory address of first word */ + unsigned int NumWords, /* number of contiguous words to write */ + DSP_WORD *pWordValues /* pointer to array of word values to write */ + ) +{ + + struct t1 *wc = wc_find_iface(DspId); + int i; + int transcount; + + if (wc && wc->vpm150m) { + for (i = 0; i < NumWords;) { + if ((NumWords - i) > VPM150M_MAX_DATA) + transcount = VPM150M_MAX_DATA; + else + transcount = NumWords - i; + t1_vpm150m_setreg(wc, transcount, DspAddress + i, &pWordValues[i]); + i += transcount; + } + } + return; + +} + + +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + * gpakHostDelay - Delay for a fixed time interval. + * + * FUNCTION + * This function delays for a fixed time interval before returning. The time + * interval is the Host Port Interface sampling period when polling a DSP for + * replies to command messages. + * + * RETURNS + * nothing + * + */ +void gpakHostDelay(void) +{ +} + + +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + * gpakLockAccess - Lock access to the specified DSP. + * + * FUNCTION + * This function aquires exclusive access to the specified DSP. + * + * RETURNS + * nothing + * + */ +void gpakLockAccess(unsigned short DspId) +{ + struct t1 *wc; + + wc = wc_find_iface(DspId); + + if (wc) { + struct vpm150m *vpm = wc->vpm150m; + + if (vpm) + down_interruptible(&vpm->sem); + } +} + + +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + * gpakUnlockAccess - Unlock access to the specified DSP. + * + * FUNCTION + * This function releases exclusive access to the specified DSP. + * + * RETURNS + * nothing + * + */ +void gpakUnlockAccess(unsigned short DspId) +{ + struct t1 *wc; + + wc = wc_find_iface(DspId); + + if (wc) { + struct vpm150m *vpm = wc->vpm150m; + + if (vpm) + up(&vpm->sem); + } +} + + +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + * gpakReadFile - Read a block of bytes from a G.PAK Download file. + * + * FUNCTION + * This function reads a contiguous block of bytes from a G.PAK Download file + * starting at the current file position. + * + * RETURNS + * The number of bytes read from the file. + * -1 indicates an error occurred. + * 0 indicates all bytes have been read (end of file) + * + */ +int gpakReadFile( + GPAK_FILE_ID FileId, /* G.PAK Download File Identifier */ + unsigned char *pBuffer, /* pointer to buffer for storing bytes */ + unsigned int NumBytes /* number of bytes to read */ + ) +{ + struct t1_firmware *fw = FileId; + unsigned int i, count; + + if (!fw || !fw->fw) + return -1; + + if (NumBytes > (fw->fw->size - fw->offset)) + count = fw->fw->size - fw->offset; + else + count = NumBytes; + + for (i = 0; i < count; i++) + pBuffer[i] = fw->fw->data[fw->offset + i]; + + fw->offset += count; + + return count; +} + +int vpm150m_config_hw(struct t1 *wc) +{ + struct vpm150m *vpm150m = wc->vpm150m; + gpakConfigPortStatus_t configportstatus; + GpakPortConfig_t portconfig; + GPAK_PortConfigStat_t pstatus; + GpakChannelConfig_t chanconfig; + GPAK_ChannelConfigStat_t cstatus; + GPAK_AlgControlStat_t algstatus; + + int res, i; + + memset(&portconfig, 0, sizeof(GpakPortConfig_t)); + + /* First Serial Port config */ + portconfig.SlotsSelect1 = SlotCfgNone; + portconfig.FirstBlockNum1 = 0; + portconfig.FirstSlotMask1 = 0x0000; + portconfig.SecBlockNum1 = 1; + portconfig.SecSlotMask1 = 0x0000; + portconfig.SerialWordSize1 = SerWordSize8; + portconfig.CompandingMode1 = cmpNone; + portconfig.TxFrameSyncPolarity1 = FrameSyncActHigh; + portconfig.RxFrameSyncPolarity1 = FrameSyncActHigh; + portconfig.TxClockPolarity1 = SerClockActHigh; + portconfig.RxClockPolarity1 = SerClockActHigh; + portconfig.TxDataDelay1 = DataDelay0; + portconfig.RxDataDelay1 = DataDelay0; + portconfig.DxDelay1 = Disabled; + portconfig.ThirdSlotMask1 = 0x0000; + portconfig.FouthSlotMask1 = 0x0000; + portconfig.FifthSlotMask1 = 0x0000; + portconfig.SixthSlotMask1 = 0x0000; + portconfig.SevenSlotMask1 = 0x0000; + portconfig.EightSlotMask1 = 0x0000; + + /* Second Serial Port config */ + portconfig.SlotsSelect2 = SlotCfg8Groups; + portconfig.FirstBlockNum2 = 0; + portconfig.FirstSlotMask2 = 0x5554; + portconfig.SecBlockNum2 = 1; + portconfig.SecSlotMask2 = 0x5555; + portconfig.ThirdSlotMask2 = 0x5555; + portconfig.FouthSlotMask2 = 0x5555; + portconfig.SerialWordSize2 = SerWordSize8; + portconfig.CompandingMode2 = cmpNone; + portconfig.TxFrameSyncPolarity2 = FrameSyncActHigh; + portconfig.RxFrameSyncPolarity2 = FrameSyncActHigh; + portconfig.TxClockPolarity2 = SerClockActHigh; + portconfig.RxClockPolarity2 = SerClockActHigh; + portconfig.TxDataDelay2 = DataDelay0; + portconfig.RxDataDelay2 = DataDelay0; + portconfig.DxDelay2 = Disabled; + portconfig.FifthSlotMask2 = 0x0001; + portconfig.SixthSlotMask2 = 0x0000; + portconfig.SevenSlotMask2 = 0x0000; + portconfig.EightSlotMask2 = 0x0000; + + /* Third Serial Port Config */ + portconfig.SlotsSelect3 = SlotCfg8Groups; + portconfig.FirstBlockNum3 = 0; + portconfig.FirstSlotMask3 = 0x5554; + portconfig.SecBlockNum3 = 1; + portconfig.SecSlotMask3 = 0x5555; + portconfig.SerialWordSize3 = SerWordSize8; + portconfig.CompandingMode3 = cmpNone; + portconfig.TxFrameSyncPolarity3 = FrameSyncActHigh; + portconfig.RxFrameSyncPolarity3 = FrameSyncActHigh; + portconfig.TxClockPolarity3 = SerClockActHigh; + portconfig.RxClockPolarity3 = SerClockActLow; + portconfig.TxDataDelay3 = DataDelay0; + portconfig.RxDataDelay3 = DataDelay0; + portconfig.DxDelay3 = Disabled; + portconfig.ThirdSlotMask3 = 0x5555; + portconfig.FouthSlotMask3 = 0x5555; + portconfig.FifthSlotMask3 = 0x0001; + portconfig.SixthSlotMask3 = 0x0000; + portconfig.SevenSlotMask3 = 0x0000; + portconfig.EightSlotMask3 = 0x0000; + + if ((configportstatus = gpakConfigurePorts(vpm150m->dspid, &portconfig, &pstatus))) { + module_printk("Configuration of ports failed (%d)!\n", configportstatus); + return -1; + } else { + debug_printk(1, "Configured McBSP ports successfully\n"); + } + + if ((res = gpakPingDsp(vpm150m->dspid, &vpm150m->version))) { + module_printk("Error pinging DSP (%d)\n", res); + return -1; + } + + for (i = 0; i < 32; i++) { + /* Let's configure a channel */ + chanconfig.PcmInPortA = 3; + chanconfig.PcmInSlotA = (i + 1) * 2; + chanconfig.PcmOutPortA = 2; + chanconfig.PcmOutSlotA = (i + 1) * 2; + chanconfig.PcmInPortB = 2; + chanconfig.PcmInSlotB = (i + 1) * 2; + chanconfig.PcmOutPortB = 3; + chanconfig.PcmOutSlotB = (i + 1) * 2; + if (vpmdtmfsupport) { + chanconfig.ToneTypesA = DTMF_tone; + chanconfig.MuteToneA = Enabled; + chanconfig.FaxCngDetA = Enabled; + } else { + chanconfig.ToneTypesA = Null_tone; + chanconfig.MuteToneA = Disabled; + chanconfig.FaxCngDetA = Disabled; + } + chanconfig.ToneTypesB = Null_tone; + chanconfig.EcanEnableA = Enabled; + chanconfig.EcanEnableB = Disabled; + chanconfig.MuteToneB = Disabled; + chanconfig.FaxCngDetB = Disabled; + + chanconfig.SoftwareCompand = cmpNone; + + chanconfig.FrameRate = rate10ms; + + chanconfig.EcanParametersA.EcanTapLength = 1024; + chanconfig.EcanParametersA.EcanNlpType = vpmnlptype; + chanconfig.EcanParametersA.EcanAdaptEnable = 1; + chanconfig.EcanParametersA.EcanG165DetEnable = 1; + chanconfig.EcanParametersA.EcanDblTalkThresh = 6; + chanconfig.EcanParametersA.EcanNlpThreshold = vpmnlpthresh; + chanconfig.EcanParametersA.EcanNlpConv = 0; + chanconfig.EcanParametersA.EcanNlpUnConv = 0; + chanconfig.EcanParametersA.EcanNlpMaxSuppress = vpmnlpmaxsupp; + chanconfig.EcanParametersA.EcanCngThreshold = 43; + chanconfig.EcanParametersA.EcanAdaptLimit = 50; + chanconfig.EcanParametersA.EcanCrossCorrLimit = 15; + chanconfig.EcanParametersA.EcanNumFirSegments = 3; + chanconfig.EcanParametersA.EcanFirSegmentLen = 64; + + chanconfig.EcanParametersB.EcanTapLength = 1024; + chanconfig.EcanParametersB.EcanNlpType = vpmnlptype; + chanconfig.EcanParametersB.EcanAdaptEnable = 1; + chanconfig.EcanParametersB.EcanG165DetEnable = 1; + chanconfig.EcanParametersB.EcanDblTalkThresh = 6; + chanconfig.EcanParametersB.EcanNlpThreshold = vpmnlpthresh; + chanconfig.EcanParametersB.EcanNlpConv = 0; + chanconfig.EcanParametersB.EcanNlpUnConv = 0; + chanconfig.EcanParametersB.EcanNlpMaxSuppress = vpmnlpmaxsupp; + chanconfig.EcanParametersB.EcanCngThreshold = 43; + chanconfig.EcanParametersB.EcanAdaptLimit = 50; + chanconfig.EcanParametersB.EcanCrossCorrLimit = 15; + chanconfig.EcanParametersB.EcanNumFirSegments = 3; + chanconfig.EcanParametersB.EcanFirSegmentLen = 64; + + if ((res = gpakConfigureChannel(vpm150m->dspid, i, tdmToTdm, &chanconfig, &cstatus))) { + module_printk("Unable to configure channel (%d)\n", res); + if (res == 1) { + module_printk("Reason %d\n", cstatus); + } + + return -1; + } + + if ((res = gpakAlgControl(vpm150m->dspid, i, BypassEcanA, &algstatus))) { + module_printk("Unable to disable echo can on channel %d (reason %d:%d)\n", i + 1, res, algstatus); + return -1; + } + + if (vpmdtmfsupport) { + if ((res = gpakAlgControl(vpm150m->dspid, i, DisableDTMFMuteA, &algstatus))) { + module_printk("Unable to disable dtmf muting on channel %d (reason %d:%d)\n", i + 1, res, algstatus); + return -1; + } + } + } + + if ((res = gpakPingDsp(vpm150m->dspid, &vpm150m->version))) { + module_printk("Error pinging DSP (%d)\n", res); + return -1; + } + + /* Turn on DTMF detection */ + if (vpmdtmfsupport) + set_bit(VPM150M_DTMFDETECT, &vpm150m->control); + set_bit(VPM150M_ACTIVE, &vpm150m->control); + + return 0; +} + +#endif diff -uNr zaptel-1.4.8/wcte12xp/.svn/text-base/vpmadt032.h.svn-base zaptel-1.4/wcte12xp/.svn/text-base/vpmadt032.h.svn-base --- zaptel-1.4.8/wcte12xp/.svn/text-base/vpmadt032.h.svn-base 1970-01-01 01:00:00.000000000 +0100 +++ zaptel-1.4/wcte12xp/.svn/text-base/vpmadt032.h.svn-base 2008-02-03 17:46:02.000000000 +0100 @@ -0,0 +1,148 @@ +/* + * Digium, Inc. Wildcard TE12xP T1/E1 card Driver + * + * Written by Michael Spiceland <mspiceland@digium.com> + * + * Adapted from the wctdm24xxp and wcte11xp drivers originally + * written by Mark Spencer <markster@digium.com> + * Matthew Fredrickson <creslin@digium.com> + * William Meadows <wmeadows@digium.com> + * + * Copyright (C) 2007, Digium, Inc. + * + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#ifndef _VPM150M_H +#define _VPM150M_H + +#include "wcte12xp.h" +#include "adt_lec.h" + +struct t1_firmware { + const struct firmware *fw; + unsigned int offset; +}; + +/* Host and DSP system dependent related definitions. */ +#define MAX_DSP_CORES 128 /* maximum number of DSP cores */ +//#define MAX_CONFS 1 /* maximum number of conferences */ +//#define MAX_PKT_CHANNELS 8 /* maximum number of packet channels */ +#define MAX_CHANNELS 32 /* maximum number of channels */ +#define MAX_WAIT_LOOPS 50 /* max number of wait delay loops */ +#define DSP_IFBLK_ADDRESS 0x0100 /* DSP address of I/F block pointer */ +#define DOWNLOAD_BLOCK_SIZE 512 /* download block size (DSP words) */ +//#define MAX_CIDPAYLOAD_BYTES 512 /* max size of a CID payload (octets) */ +typedef unsigned short DSP_WORD; /* 16 bit DSP word */ +typedef unsigned int DSP_ADDRESS; /* 32 bit DSP address */ +typedef struct t1_firmware* GPAK_FILE_ID; /* G.PAK Download file identifier */ + +#define __VPM150M_RWPAGE (1 << 4) +#define __VPM150M_RD (1 << 3) +#define __VPM150M_WR (1 << 2) +#define __VPM150M_FIN (1 << 1) +#define __VPM150M_TX (1 << 0) + +#define VPM150M_HPI_CONTROL 0x00 +#define VPM150M_HPI_ADDRESS 0x02 +#define VPM150M_HPI_DATA 0x03 + +#define VPM150M_MAX_COMMANDS 8 + +/* Some Bit ops for different operations */ +#define VPM150M_SPIRESET 0 +#define VPM150M_HPIRESET 1 +#define VPM150M_SWRESET 2 +#define VPM150M_DTMFDETECT 3 +#define VPM150M_ACTIVE 4 +#define VPM150M_MAX_DATA 1 + +struct vpm150m_cmd { + unsigned short address; + unsigned short data[VPM150M_MAX_DATA]; + unsigned char ident; + unsigned char datalen; + unsigned int flags; + unsigned char cs_slot; +}; + +struct vpm150m { + unsigned short dspid; + unsigned long control; + unsigned char curpage; + unsigned short version; + struct vpm150m_cmd cmdq[VPM150M_MAX_COMMANDS]; + spinlock_t lock; /* control access to list of bottom half tasks */ + struct semaphore sem; + struct workqueue_struct *wq; + struct work_struct work_dtmf; + struct work_struct work_debug; + struct work_struct work_echocan; + struct list_head worklist; + unsigned char curtone[32]; + unsigned long curdtmfmutestate; + unsigned long desireddtmfmutestate; + struct adt_lec_params chan_params[32]; + struct t1 *wc; +}; + +/* linked list for vpm echocan workqueue*/ +struct vpm150m_workentry { + struct list_head list; + struct t1 *wc; /* what card are we dealing with? */ + struct zt_chan *chan; /* what channels are we going to deal with? */ + struct adt_lec_params params; /* how should we behave? */ +}; + +extern int debug; +extern int vpmsupport; +extern int vpmdtmfsupport; +extern struct pci_driver te12xp_driver; + +void t1_vpm150m_init(struct t1 *wc); +void vpm150m_cmd_dequeue(struct t1 *wc, volatile unsigned char *writechunk, int whichframe); +void vpm150m_cmd_decipher(struct t1 *wc, volatile unsigned char *readchunk); +int vpm150m_config_hw(struct t1 *wc); + +/* gpak API functions */ +void gpakReadDspMemory( + unsigned short int DspId, /* DSP Identifier (0 to MAX_DSP_CORES-1) */ + DSP_ADDRESS DspAddress, /* DSP's memory address of first word */ + unsigned int NumWords, /* number of contiguous words to read */ + DSP_WORD *pWordValues /* pointer to array of word values variable */ + ); +void gpakWriteDspMemory( + unsigned short int DspId, /* DSP Identifier (0 to MAX_DSP_CORES-1) */ + DSP_ADDRESS DspAddress, /* DSP's memory address of first word */ + unsigned int NumWords, /* number of contiguous words to write */ + DSP_WORD *pWordValues /* pointer to array of word values to write */ + ); +void gpakHostDelay(void); +void gpakLockAccess( + unsigned short int DspId /* DSP Identifier (0 to MAX_DSP_CORES-1) */ + ); +void gpakUnlockAccess( + unsigned short int DspId /* DSP Identifier (0 to MAX_DSP_CORES-1) */ + ); +int gpakReadFile( + GPAK_FILE_ID FileId, /* G.PAK Download File Identifier */ + unsigned char *pBuffer, /* pointer to buffer for storing bytes */ + unsigned int NumBytes /* number of bytes to read */ + ); + +#endif diff -uNr zaptel-1.4.8/wcte12xp/.svn/text-base/wcte12xp.h.svn-base zaptel-1.4/wcte12xp/.svn/text-base/wcte12xp.h.svn-base --- zaptel-1.4.8/wcte12xp/.svn/text-base/wcte12xp.h.svn-base 1970-01-01 01:00:00.000000000 +0100 +++ zaptel-1.4/wcte12xp/.svn/text-base/wcte12xp.h.svn-base 2008-02-03 17:46:02.000000000 +0100 @@ -0,0 +1,179 @@ +/* + * Digium, Inc. Wildcard TE12xP T1/E1 card Driver + * + * Written by Michael Spiceland <mspiceland@digium.com> + * + * Adapted from the wctdm24xxp and wcte11xp drivers originally + * written by Mark Spencer <markster@digium.com> + * Matthew Fredrickson <creslin@digium.com> + * William Meadows <wmeadows@digium.com> + * + * Copyright (C) 2007, Digium, Inc. + * + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#ifndef _WCTE12XP_H +#define _WCTE12XP_H + +#ifdef LINUX26 +/* Comment to disable VPM support */ +#define VPM_SUPPORT 1 +#endif + +#define WC_MAX_IFACES 8 + +#ifdef VPM_SUPPORT +#define MAX_TDM_CHAN 31 +#endif + +#define SDI_CLK (0x00010000) +#define SDI_DOUT (0x00020000) +#define SDI_DREAD (0x00040000) +#define SDI_DIN (0x00080000) + +#define EFRAME_SIZE 108 +#define ERING_SIZE 16 /* Maximum ring size */ +#define EFRAME_GAP 20 +#define SFRAME_SIZE ((EFRAME_SIZE * ZT_CHUNKSIZE) + (EFRAME_GAP * (ZT_CHUNKSIZE - 1))) + +#define PCI_WINDOW_SIZE ((2 * 2 * 2 * SFRAME_SIZE) + (2 * ERING_SIZE * 4)) + +#define MAX_COMMANDS 7*7*2 /* 42 bytes /3 (cntl,addr,data) /2 (cs) */ + +#define ISR_COMMANDS 2 +#define NUM_EC 4 + +#define __CMD_VPM (1 << 16) /* flag for VPM action */ +#define __CMD_ISR (1 << 17) /* flag for ISR reads */ +#define __CMD_PINS (1 << 18) /* CPLD pin read */ +#define __CMD_LEDS (1 << 19) /* LED Operation */ +#define __CMD_RD (1 << 20) /* Read Operation */ +#define __CMD_WR (1 << 21) /* Write Operation */ +#define __CMD_FIN (1 << 22) /* Has finished receive */ +#define __CMD_TX (1 << 23) /* Has been transmitted */ + +#define __LED_ORANGE (1<<3) +#define __LED_GREEN (1<<2) +#define __LED_RED (1<<1) + +#define SET_LED_ORANGE(a) a | __LED_ORANGE +#define SET_LED_RED(a) (a | __LED_RED) & ~__LED_GREEN +#define SET_LED_GREEN(a) (a | __LED_GREEN) & ~__LED_RED + +#define UNSET_LED_ORANGE(a) a & ~__LED_ORANGE +#define UNSET_LED_REDGREEN(a) a | __LED_RED | __LED_GREEN + +#define CMD_WR(a,b) (((a) << 8) | (b) | __CMD_WR) +#define CMD_RD(a) (((a) << 8) | __CMD_RD) +#define CMD_LEDS(a) (((a) << 8) | __CMD_LEDS) +//#define CMD_BYTE(slot, a) (slot*6)+(a*2) /* only even slots */ +#define CMD_BYTE(slot, a, is_vpm) (slot*6)+(a*2)+is_vpm /* only even slots */ +//TODO: make a separate macro + +#define TYPE_T1 1 +#define TYPE_E1 2 + +#define NOT_VPM -1 + +#define module_printk(fmt, args...) printk("%s: " fmt, te12xp_driver.name, ## args) +#define debug_printk(level, fmt, args...) if (debug >= level) printk("%s (%s): " fmt, te12xp_driver.name, __FUNCTION__, ## args) +extern spinlock_t ifacelock; + +struct command { + unsigned short address; + unsigned char data; + unsigned char ident; + unsigned int flags; + unsigned char cs_slot; + unsigned char vpm_num; /* ignored for all but vpm commmands */ +}; + +struct cmdq { + struct command cmds[MAX_COMMANDS]; + unsigned char isrshadow[ISR_COMMANDS]; +}; + +struct vpm150m; + +struct t1 { + struct pci_dev *dev; + spinlock_t reglock; + unsigned char txident; + unsigned char rxident; + unsigned char statreg; /* bit 0 = vpmadt032 int */ + int spantype; + struct { + unsigned int nmf:1; + unsigned int sendingyellow:1; + } flags; + unsigned char txsigs[16]; /* Copy of tx sig registers */ + int num; + int alarmcount; /* How much red alarm we've seen */ + int alarmdebounce; + char *variety; + unsigned int intcount; + int sync; + int dead; + int blinktimer; + int alarmtimer; + int yellowtimer; + int ledlastvalue; + int alarms_read; + int checktiming; /* Set >0 to cause the timing source to be checked */ + int loopupcnt; + int loopdowncnt; + int initialized; + int *chanmap; + unsigned char ledtestreg; + unsigned long iobase; + unsigned char ec_chunk1[32][ZT_CHUNKSIZE]; + unsigned char ec_chunk2[32][ZT_CHUNKSIZE]; + struct zt_span span; /* Span */ + struct zt_chan chans[32]; /* Channels */ + int freeregion; + unsigned int intmask; + wait_queue_head_t regq; + struct cmdq cmdq; + struct command dummy; /* preallocate for dummy noop command */ + unsigned char ctlreg; + int rdbl; + int tdbl; + unsigned int rxints; + unsigned int txints; + unsigned int sdi; + int usecount; + dma_addr_t readdma; + dma_addr_t writedma; + dma_addr_t descripdma; + volatile unsigned int *writechunk; + volatile unsigned int *readchunk; + volatile unsigned int *descripchunk; + unsigned int isrreaderrors; +#ifdef VPM_SUPPORT + int vpm; + struct vpm150m *vpm150m; + unsigned long dtmfactive; + unsigned long dtmfmask; + unsigned long dtmfmutemask; +#endif +}; + +int schluffen(wait_queue_head_t *q); + +#endif diff -uNr zaptel-1.4.8/wcte12xp/vpmadt032.c zaptel-1.4/wcte12xp/vpmadt032.c --- zaptel-1.4.8/wcte12xp/vpmadt032.c 2008-01-11 00:15:28.000000000 +0100 +++ zaptel-1.4/wcte12xp/vpmadt032.c 2008-02-03 17:46:02.000000000 +0100 @@ -42,6 +42,10 @@ extern struct t1 *ifaces[WC_MAX_IFACES]; +extern int vpmnlptype; +extern int vpmnlpthresh; +extern int vpmnlpmaxsupp; + #ifdef VPM_SUPPORT inline void vpm150m_cmd_dequeue(struct t1 *wc, volatile unsigned char *writechunk, int whichframe) @@ -1314,14 +1318,14 @@ chanconfig.FrameRate = rate10ms; chanconfig.EcanParametersA.EcanTapLength = 1024; - chanconfig.EcanParametersA.EcanNlpType = 1; + chanconfig.EcanParametersA.EcanNlpType = vpmnlptype; chanconfig.EcanParametersA.EcanAdaptEnable = 1; chanconfig.EcanParametersA.EcanG165DetEnable = 1; chanconfig.EcanParametersA.EcanDblTalkThresh = 6; - chanconfig.EcanParametersA.EcanNlpThreshold = 24; + chanconfig.EcanParametersA.EcanNlpThreshold = vpmnlpthresh; chanconfig.EcanParametersA.EcanNlpConv = 0; chanconfig.EcanParametersA.EcanNlpUnConv = 0; - chanconfig.EcanParametersA.EcanNlpMaxSuppress = 0; + chanconfig.EcanParametersA.EcanNlpMaxSuppress = vpmnlpmaxsupp; chanconfig.EcanParametersA.EcanCngThreshold = 43; chanconfig.EcanParametersA.EcanAdaptLimit = 50; chanconfig.EcanParametersA.EcanCrossCorrLimit = 15; @@ -1329,14 +1333,14 @@ chanconfig.EcanParametersA.EcanFirSegmentLen = 64; chanconfig.EcanParametersB.EcanTapLength = 1024; - chanconfig.EcanParametersB.EcanNlpType = 1; + chanconfig.EcanParametersB.EcanNlpType = vpmnlptype; chanconfig.EcanParametersB.EcanAdaptEnable = 1; chanconfig.EcanParametersB.EcanG165DetEnable = 1; chanconfig.EcanParametersB.EcanDblTalkThresh = 6; - chanconfig.EcanParametersB.EcanNlpThreshold = 24; + chanconfig.EcanParametersB.EcanNlpThreshold = vpmnlpthresh; chanconfig.EcanParametersB.EcanNlpConv = 0; chanconfig.EcanParametersB.EcanNlpUnConv = 0; - chanconfig.EcanParametersB.EcanNlpMaxSuppress = 0; + chanconfig.EcanParametersB.EcanNlpMaxSuppress = vpmnlpmaxsupp; chanconfig.EcanParametersB.EcanCngThreshold = 43; chanconfig.EcanParametersB.EcanAdaptLimit = 50; chanconfig.EcanParametersB.EcanCrossCorrLimit = 15; diff -uNr zaptel-1.4.8/wcte12xp/wcte12xp.h zaptel-1.4/wcte12xp/wcte12xp.h --- zaptel-1.4.8/wcte12xp/wcte12xp.h 2007-12-08 18:28:28.000000000 +0100 +++ zaptel-1.4/wcte12xp/wcte12xp.h 2008-02-03 17:46:02.000000000 +0100 @@ -31,8 +31,10 @@ #ifndef _WCTE12XP_H #define _WCTE12XP_H +#ifdef LINUX26 /* Comment to disable VPM support */ #define VPM_SUPPORT 1 +#endif #define WC_MAX_IFACES 8