diff options
-rwxr-xr-x | torisa.c | 19 | ||||
-rwxr-xr-x | wct1xxp.c | 111 | ||||
-rwxr-xr-x | zaptel.h | 107 | ||||
-rwxr-xr-x | ztcfg.c | 33 |
4 files changed, 216 insertions, 54 deletions
@@ -302,7 +302,7 @@ static void make_chans(void) c = x * channels_per_span + y; sprintf(chans[c].name, "TorISA/%d/%d", x + 1, y + 1); chans[c].sigcap = ZT_SIG_EM | ZT_SIG_CLEAR | ZT_SIG_FXSLS | ZT_SIG_FXSGS | ZT_SIG_FXSKS | - ZT_SIG_FXOLS | ZT_SIG_FXOGS | ZT_SIG_FXOKS; + ZT_SIG_FXOLS | ZT_SIG_FXOGS | ZT_SIG_FXOKS | ZT_SIG_CAS; chans[c].pvt = &pvts[c]; pvts[c].span = x; chans[c].chanpos = y + 1; @@ -669,16 +669,25 @@ static struct tasklet_struct torisa_tlet; static void torisa_tasklet(unsigned long data) { - + int x; + taskletrun++; if (taskletpending) { taskletexec++; /* Perform receive data calculations. Reverse to run most likely master last */ - if (spans[1].flags & ZT_FLAG_RUNNING) + if (spans[1].flags & ZT_FLAG_RUNNING) { + /* Perform echo cancellation */ + for (x=0;x<channels_per_span;x++) + zt_ec_chunk(&spans[1].chans[x], spans[1].chans[x].readchunk, writedata[1-curread][x + channels_per_span]); zt_receive(&spans[1]); - if (spans[0].flags & ZT_FLAG_RUNNING) + } + if (spans[0].flags & ZT_FLAG_RUNNING) { + /* Perform echo cancellation */ + for (x=0;x<channels_per_span;x++) + zt_ec_chunk(&spans[0].chans[x], spans[0].chans[x].readchunk, writedata[1-curread][x]); zt_receive(&spans[0]); + } /* Prepare next set for transmission */ if (spans[1].flags & ZT_FLAG_RUNNING) @@ -751,7 +760,7 @@ static void torisa_intr(int irq, void *dev_id, struct pt_regs *regs) if (!taskletpending) { taskletpending = 1; taskletsched++; - tasklet_hi_schedule(&torisa_tlet); + tasklet_hi_schedule(&torisa_tlet); } else { txerrors++; } @@ -124,6 +124,7 @@ struct t1xxp { char *variety; int intcount; int usecount; + int sync; int dead; int blinktimer; int alarmtimer; @@ -225,7 +226,13 @@ static int control_set_reg(struct t1xxp *wc, int reg, unsigned char val) static int __control_get_reg(struct t1xxp *wc, int reg) { unsigned char res; - __select_control(wc); + /* The following makes UTTERLY no sense, but what was happening + was that reads in some cases were not actually happening + on the physical bus. Why, we dunno. But in debugging, we found + that writing before reading (in this case to an unused position) + seems to get rid of the problem */ + __control_set_reg(wc,3,0x69); /* do magic here */ + /* now get the read byte from the Xilinx part */ res = inb(wc->ioaddr + WC_USERREG + ((reg & 0xf) << 2)); return res; } @@ -290,6 +297,20 @@ static void __t1xxp_disable_interrupts(struct t1xxp *wc) outb(0x00, wc->ioaddr + WC_MASK1); } +static void __t1xxp_set_clear(struct t1xxp *wc) +{ + /* Setup registers */ + int x,y; + unsigned char b; + for (x=0;x<3;x++) { + b = 0; + for (y=0;y<8;y++) + if (wc->chans[x * 8 + y].sig & ZT_SIG_CLEAR) + b |= (1 << y); + __t1_set_reg(wc, 0x39 + x, b); + } +} + static void t1xxp_framer_start(struct t1xxp *wc) { int i; @@ -327,6 +348,9 @@ static void t1xxp_framer_start(struct t1xxp *wc) printk("Using %s/%s coding/framing\n", coding, framing); if (!alreadyrunning) { + /* Setup the clear channels */ + __t1xxp_set_clear(wc); + /* Set LIRST bit to 1 */ __t1_set_reg(wc, 0x0a, 0x80); spin_unlock_irqrestore(&wc->lock, flags); @@ -368,7 +392,7 @@ static int t1xxp_framer_hard_reset(struct t1xxp *wc) spin_lock_irqsave(&wc->lock, flags); /* Initialize all registers to 0 */ - for (x=0x0;x<0x96;x++) + for (x=0x0;x<192;x++) __t1_set_reg(wc, x, 0); /* Full-on sync required */ @@ -390,6 +414,7 @@ static int t1xxp_framer_hard_reset(struct t1xxp *wc) __t1_set_reg(wc, 0x12, 0x22); __t1_set_reg(wc, 0x14, 0x80); __t1_set_reg(wc, 0x15, 0x80); + spin_unlock_irqrestore(&wc->lock, flags); return 0; } @@ -442,10 +467,13 @@ static int t1xxp_ioctl(struct zt_chan *chan, unsigned int cmd, unsigned long dat static int t1xxp_startup(struct zt_span *span) { struct t1xxp *wc = span->pvt; + + int alreadyrunning = span->flags & ZT_FLAG_RUNNING; /* Reset framer with proper parameters and start */ t1xxp_framer_start(wc); + printk("Calling startup (flags is %d)\n", span->flags); - if (!(span->flags & ZT_FLAG_RUNNING)) { + if (!alreadyrunning) { /* Only if we're not already going */ t1xxp_enable_interrupts(wc); t1xxp_start_dma(wc); @@ -475,20 +503,6 @@ static int t1xxp_maint(struct zt_span *span, int mode) return -1; } -static void __t1xxp_set_clear(struct t1xxp *wc) -{ - /* Setup registers */ - int x,y; - unsigned char b; - for (x=0;x<3;x++) { - b = 0; - for (y=0;y<8;y++) - if (wc->chans[x * 8 + y].sig & ZT_SIG_CLEAR) - b |= (1 << y); - __t1_set_reg(wc, 0x39 + x, b); - } -} - static int t1xxp_chanconfig(struct zt_chan *chan, int sigtype) { struct t1xxp *wc = chan->pvt; @@ -506,11 +520,13 @@ static int t1xxp_chanconfig(struct zt_chan *chan, int sigtype) static int t1xxp_spanconfig(struct zt_span *span, struct zt_lineconfig *lc) { + struct t1xxp *wc = span->pvt; span->lineconfig = lc->lineconfig; span->txlevel = lc->lbo; span->rxlevel = 0; /* Do we want to SYNC on receive or not */ - span->syncsrc = lc->sync; + span->syncsrc = 0; + wc->sync = lc->sync; /* If already running, apply changes immediately */ if (span->flags & ZT_FLAG_RUNNING) return t1xxp_startup(span); @@ -553,7 +569,7 @@ static int t1xxp_software_init(struct t1xxp *wc) wc->chans[x].sigcap = ZT_SIG_EM | ZT_SIG_CLEAR | ZT_SIG_FXSLS | ZT_SIG_FXSGS | ZT_SIG_FXSKS | ZT_SIG_FXOLS | - ZT_SIG_FXOGS | ZT_SIG_FXOKS; + ZT_SIG_FXOGS | ZT_SIG_FXOKS | ZT_SIG_CAS; wc->chans[x].pvt = wc; wc->chans[x].chanpos = x + 1; } @@ -568,6 +584,7 @@ static inline void __handle_leds(struct t1xxp *wc) { int oldreg; wc->blinktimer++; + if (wc->span.alarms & (ZT_ALARM_RED | ZT_ALARM_BLUE)) { /* Red/Blue alarm */ #ifdef FANCY_ALARM @@ -639,7 +656,7 @@ static void t1xxp_receiveprep(struct t1xxp *wc, int ints) volatile unsigned char *rxbuf; int x; int y; - if (ints & 0x08) { + if (ints & 0x04) { /* Just received first buffer */ rxbuf = wc->readchunk; } else { @@ -663,6 +680,11 @@ static void t1xxp_receiveprep(struct t1xxp *wc, int ints) rxbuf[32 * y + ((chanmap[x] + WC_OFFSET + wc->offset) & 0x1f)]; } } + /* XXX We should apply echo cancellation closer -- we're wasting + 8 taps XXX */ + for (x=0;x<24;x++) + zt_ec_chunk(&wc->chans[x], wc->chans[x].readchunk, wc->chans[x].writechunk); + zt_receive(&wc->span); } @@ -671,7 +693,7 @@ static void __t1xxp_check_sigbits(struct t1xxp *wc, int x) int a,b,i,y,rxs; a = __t1_get_reg(wc, 0x60 + x); - b = __t1_get_reg(wc, 0x64 + x); + b = __t1_get_reg(wc, 0x63 + x); for (y=0;y<8;y++) { i = x * 8 + y; rxs = 0; @@ -688,7 +710,7 @@ static void __t1xxp_check_sigbits(struct t1xxp *wc, int x) static void __t1xxp_check_alarms(struct t1xxp *wc) { - unsigned char c; + unsigned char c,d; int alarms; int x,j; @@ -697,8 +719,8 @@ static void __t1xxp_check_alarms(struct t1xxp *wc) wc->span.rxlevel = c >> 6; /* Get status register s*/ - __t1_set_reg(wc, 0x20, 0xff); - c = __t1_get_reg(wc, 0x20); + __t1_set_reg(wc, 0x20, 0xff); + c = __t1_get_reg(wc, 0x20); /* Assume no alarms */ alarms = 0; @@ -722,32 +744,50 @@ static void __t1xxp_check_alarms(struct t1xxp *wc) alarms |= ZT_ALARM_BLUE; /* Keep track of recovering */ - if (!alarms && wc->span.alarms) + if ((!alarms) && wc->span.alarms) wc->alarmtimer = ZT_ALARMSETTLE_TIME; - if (wc->alarmtimer) - alarms |= ZT_ALARM_RECOVER; /* If receiving alarms, go into Yellow alarm state */ - if (alarms && !wc->span.alarms) { + if (alarms && (!wc->span.alarms)) { +#if 0 printk("Going into yellow alarm\n"); - __t1_set_reg(wc, 0x35, 0x11); +#endif + __t1_set_reg(wc, 0x35, 0x11); } + if (wc->span.alarms != alarms) { + d = __control_get_reg(wc, 0); + start_alarm(wc); + if (!(alarms & (ZT_ALARM_RED | ZT_ALARM_BLUE | ZT_ALARM_LOOPBACK)) && + wc->sync) { + /* Use the recieve signalling */ + wc->span.syncsrc = wc->span.spanno; + d |= 1; + } else { + wc->span.syncsrc = 0; + d &= ~1; + } + __control_set_reg(wc, 0, d); + } + if (wc->alarmtimer) + alarms |= ZT_ALARM_RECOVER; if (c & 0x4) alarms |= ZT_ALARM_YELLOW; wc->span.alarms = alarms; + zt_alarm_notify(&wc->span); - } static void __t1xxp_do_counters(struct t1xxp *wc) { if (wc->alarmtimer) { if (!--wc->alarmtimer) { - wc->span.alarms &= ~ZT_ALARM_RECOVER; + wc->span.alarms &= ~(ZT_ALARM_RECOVER); /* Clear yellow alarm */ - printk("Coming out of yellow alarm\n"); +#if 0 + printk("Coming out of alarm\n"); +#endif __t1_set_reg(wc, 0x35, 0x10); zt_alarm_notify(&wc->span); } @@ -777,7 +817,9 @@ static void t1xxp_interrupt(int irq, void *dev_id, struct pt_regs *regs) } spin_lock_irqsave(&wc->lock, flags); +#if 1 __handle_leds(wc); +#endif /* Count down timers */ __t1xxp_do_counters(wc); @@ -788,10 +830,7 @@ static void t1xxp_interrupt(int irq, void *dev_id, struct pt_regs *regs) case 0: case 1: case 2: - case 3: -#if 0 __t1xxp_check_sigbits(wc, x); -#endif break; case 4: __t1xxp_check_alarms(wc); @@ -902,7 +941,7 @@ static int __devinit t1xxp_init_one(struct pci_dev *pdev, const struct pci_devic /* Keep track of which device we are */ pci_set_drvdata(pdev, wc); - if (request_irq(pdev->irq, t1xxp_interrupt, SA_SHIRQ, "t1xxp", wc)) { + if (request_irq(pdev->irq, t1xxp_interrupt, SA_INTERRUPT | SA_SHIRQ, "t1xxp", wc)) { printk("t1xxp: Unable to request IRQ %d\n", pdev->irq); kfree(wc); return -EIO; @@ -38,7 +38,16 @@ #include <linux/ppp_channel.h> #endif #include <linux/fs.h> + +#if defined(ECHO_CAN_STEVE) #include "sec.h" +#elif defined(ECHO_CAN_STEVE2) +#include "sec-2.h" +#else +#include "mec.h" +#endif + +#include "ecdis.h" #include "fasthdlc.h" #endif #ifdef CONFIG_DEVFS_FS @@ -88,6 +97,7 @@ #define ZT_SIG_HDLCFCS ((1 << 9) | ZT_SIG_HDLCRAW) /* HDLC with FCS calculation */ #define ZT_SIG_HDLCNET ((1 << 10) | ZT_SIG_HDLCFCS) /* HDLC Network */ #define ZT_SIG_SLAVE (1 << 11) /* Slave to another channel */ +#define ZT_SIG_CAS (1 << 12) /* Just get bits */ #define ZT_ABIT 8 #define ZT_BBIT 4 @@ -102,9 +112,10 @@ variable sometime. 8 samples = 1 ms = most frequent service interval possible for a USB device */ #define ZT_CHUNKSIZE 8 -#define ZT_MIN_CHUNKSIZE 8 -#define ZT_DEFAULT_CHUNKSIZE 8 -#define ZT_MAX_CHUNKSIZE 8 +#define ZT_MIN_CHUNKSIZE ZT_CHUNKSIZE +#define ZT_DEFAULT_CHUNKSIZE ZT_CHUNKSIZE +#define ZT_MAX_CHUNKSIZE ZT_CHUNKSIZE +#define ZT_CB_SIZE 2 #define ZT_MAX_BLOCKSIZE 8192 #define ZT_DEFAULT_NUM_BUFS 2 @@ -129,6 +140,7 @@ int txbits; /* read-only */ int txhooksig; /* read-only */ int rxhooksig; /* read-only */ int curlaw; /* read-only -- one of ZT_LAW_MULAW or ZT_LAW_ALAW */ +int idlebits; /* read-only -- What is considered the idle state */ char name[40]; /* Name of channel */ int prewinktime; int preflashtime; @@ -175,7 +187,7 @@ unsigned char rxgain[256]; /* Receive gain table */ unsigned char txgain[256]; /* Transmit gain table */ } ZT_GAINS; -struct zt_lineconfig +typedef struct zt_lineconfig { int span; /* Which span number (0 to use name) */ char name[20]; /* Name of span to use */ @@ -184,13 +196,14 @@ int lineconfig; /* line config parameters (framing, coding) */ int sync; /* what level of sync source we are */ } ZT_LINECONFIG; -struct zt_chanconfig +typedef struct zt_chanconfig { int chan; /* Channel we're applying this to (0 to use name) */ char name[40]; /* Name of channel to use */ int sigtype; /* Signal type */ int deflaw; /* Default law (ZT_LAW_DEFAULT, ZT_LAW_MULAW, or ZT_LAW_ALAW */ int master; /* Master channel if sigtype is ZT_SLAVE */ +int idlebits; /* Idle bits (if this is a CAS channel) */ } ZT_CHANCONFIG; typedef struct zt_bufferinfo @@ -456,6 +469,16 @@ char dialstr[ZT_MAX_DTMF_BUF]; #define ZT_HDLCPPP _IOW (ZT_CODE, 41, int) /* + * Set the ring cadence for FXS interfaces + */ +#define ZT_SETCADENCE _IOW (ZT_CODE, 42, struct zt_ring_cadence) + +/* + * Set the bits going out for CAS interface + */ +#define ZT_SETTXBITS _IOW (ZT_CODE, 43, int) + +/* * 60-80 are reserved for private drivers * 80-85 are reserved for dynamic span stuff */ @@ -495,6 +518,10 @@ char dialstr[ZT_MAX_DTMF_BUF]; #define ZT_MAX_CADENCE 16 +struct zt_ring_cadence { + int ringcadence [ZT_MAX_CADENCE]; +}; + struct zt_tone_def_header { int count; /* How many samples follow */ int zone; /* Which zone we are loading */ @@ -623,6 +650,9 @@ struct zt_tone_def { /* Structure for zone programming */ /* Ret Value for hook change complete */ #define ZT_EVENT_HOOKCOMPLETE 12 +/* Ret Value for bits changing on a CAS / User channel */ +#define ZT_EVENT_BITSCHANGED 13 + /* Flag Value for IOMUX, read avail */ #define ZT_IOMUX_READ 1 @@ -725,6 +755,14 @@ struct zt_hdlc { }; #endif +/* Conference queue stucture */ +struct confq { + u_char buffer[ZT_CHUNKSIZE * ZT_CB_SIZE]; + u_char *buf[ZT_CB_SIZE]; + int inbuf; + int outbuf; +}; + struct zt_chan { #ifdef CONFIG_ZAPATA_NET /* Must be first */ @@ -740,10 +778,10 @@ struct zt_chan { int chanpos; int flags; - /* Slaves */ - unsigned int slavemask; - struct zt_chan *master; /* Our Master channel (could be us) */ + /* Next slave (if appropriate) */ + int nextslave; + u_char *writechunk; /* Actual place to write to */ u_char swritechunk[ZT_MAX_CHUNKSIZE]; /* Buffer to be written */ u_char *readchunk; /* Actual place to read from */ @@ -806,6 +844,9 @@ struct zt_chan { int tonep; /* Current position in tone */ struct zt_tone_state ts; /* Tone state */ + /* Ring cadence */ + int ringcadence[ZT_MAX_CADENCE]; + /* Digit string dialing stuff */ int digitmode; /* What kind of tones are we sending? */ char txdialbuf[ZT_MAX_DTMF_BUF]; @@ -823,10 +864,17 @@ struct zt_chan { int infcs; /* Conferencing stuff */ - int confn; /* conference number */ + int confna; /* conference number (alias) */ + int _confn; /* Actual conference number */ int confmode; /* conference mode */ int confmute; /* conference mute mode */ + /* Incoming and outgoing conference chunk queues for + communicating between zaptel master time and + other boards */ + struct confq confin; + struct confq confout; + short getlin[ZT_MAX_CHUNKSIZE]; /* Last transmitted samples */ short getlin_lastchunk[ZT_MAX_CHUNKSIZE]; /* Last transmitted samples from last chunk */ short putlin[ZT_MAX_CHUNKSIZE]; /* Last received samples */ @@ -838,6 +886,8 @@ struct zt_chan { /* Is echo cancellation enabled or disabled */ int echocancel; echo_can_state_t *ec; + echo_can_disable_detector_state_t txecdis; + echo_can_disable_detector_state_t rxecdis; /* RBS timings */ int prewinktime; /* pre-wink time (ms) */ @@ -865,9 +915,16 @@ struct zt_chan { int txhooksig; int kewlonhook; + /* Idle signalling if CAS signalling */ + int idlebits; + int deflaw; /* 1 = mulaw, 2=alaw, 0=undefined */ short *xlaw; +#ifdef CONFIG_CALC_XLAW + unsigned char (*lineartoxlaw)(short a); +#else unsigned char *lin2x; +#endif #ifdef CONFIG_DEVFS_FS devfs_handle_t fhandle; /* File handle in devfs for the channel */ @@ -1063,10 +1120,25 @@ extern void zt_init_tone_state(struct zt_tone_state *ts, struct zt_tone *zt); Set 'mf' to 0 for DTMF or 1 for MFv1 */ extern struct zt_tone *zt_dtmf_tone(char digit, int mf); +/* Echo cancel a receive and transmit chunk for a given channel. This + should be called by the low-level driver as close to the interface + as possible. ECHO CANCELLATION IS NO LONGER AUTOMATICALLY DONE + AT THE ZAPTEL LEVEL. zt_ec_chunk will not echo cancel if it should + not be doing so. rxchunk is modified in-place */ + +extern void zt_ec_chunk(struct zt_chan *chan, unsigned char *rxchunk, const unsigned char *txchunk); + /* Don't use these directly -- they're not guaranteed to be there. */ extern short __zt_mulaw[256]; +extern short __zt_alaw[256]; +#ifdef CONFIG_CALC_XLAW +extern u_char __zt_lineartoulaw(short a); +extern u_char __zt_lineartoalaw(short a); +#else extern u_char __zt_lin2mu[16384]; +extern u_char __zt_lin2a[16384]; +#endif /* Used by dynamic zaptel -- don't use directly */ extern void zt_set_dynamic_ioctl(int (*func)(unsigned int cmd, unsigned long data)); @@ -1104,16 +1176,25 @@ static inline short zt_tone_nextsample(struct zt_tone_state *ts, struct zt_tone /* These are the right functions to use. */ -#define ZT_LIN2MU(a) (__zt_lin2mu[((unsigned short)(a)) >> 2]) #define ZT_MULAW(a) (__zt_mulaw[(a)]) +#define ZT_ALAW(a) (__zt_alaw[(a)]) +#define ZT_XLAW(a,c) (c->xlaw[(a)]) + +#ifdef CONFIG_CALC_XLAW +#define ZT_LIN2MU(a) (__zt_lineartoulaw((a))) +#define ZT_LIN2A(a) (__zt_lineartoalaw((a))) + +#define ZT_LIN2X(a,c) ((c)->lineartoxlaw((a))) +#else +/* Use tables */ +#define ZT_LIN2MU(a) (__zt_lin2mu[((unsigned short)(a)) >> 2]) #define ZT_LIN2A(a) (__zt_lin2a[((unsigned short)(a)) >> 2]) -#define ZT_ALAW(a) (__zt_alaw[(a)]) /* Manipulate as appropriate for x-law */ #define ZT_LIN2X(a,c) ((c)->lin2x[((unsigned short)(a)) >> 2]) -#define ZT_XLAW(a,c) (c->xlaw[(a)]) -#endif +#endif /* CONFIG_CALC_XLAW */ +#endif /* __KERNEL__ */ #endif /* _LINUX_ZAPTEL_H */ @@ -332,13 +332,39 @@ int apply_channels(int chans[], char *argstr) return res; } +int parse_idle(int *i, char *s) +{ + char a,b,c,d; + if (s) { + if (sscanf(s, "%c%c%c%c", &a,&b,&c,&d) == 4) { + if (((a == '0') || (a == '1')) && ((b == '0') || (b == '1')) && ((c == '0') || (c == '1')) && ((d == '0') || (d == '1'))) { + *i = 0; + if (a == '1') + *i |= ZT_ABIT; + if (b == '1') + *i |= ZT_BBIT; + if (c == '1') + *i |= ZT_CBIT; + if (d == '1') + *i |= ZT_DBIT; + return 0; + } + } + } + error("CAS Signalling requires idle definition in the form ':xxxx' at the end of the channel definition, where xxxx represent the a, b, c, and d bits\n"); + return -1; +} + static int chanconfig(char *keyword, char *args) { int chans[ZT_MAX_CHANNELS]; int res; int x; int master=0; + char *idle; bzero(chans, sizeof(chans)); + strtok(args, ":"); + idle = strtok(NULL, ":"); res = apply_channels(chans, args); if (res <= 0) return -1; @@ -372,6 +398,11 @@ static int chanconfig(char *keyword, char *args) } else if (!strcasecmp(keyword, "fxoks")) { sig[x] = "FXO Kewlstart"; cc[x].sigtype = ZT_SIG_FXOKS; + } else if (!strcasecmp(keyword, "cas") || !strcasecmp(keyword, "user")) { + if (parse_idle(&cc[x].idlebits, idle)) + return -1; + sig[x] = "CAS / User"; + cc[x].sigtype = ZT_SIG_CAS; } else if (!strcasecmp(keyword, "unused")) { sig[x] = "Unused"; cc[x].sigtype = 0; @@ -539,6 +570,8 @@ static struct handler { { "indclear", chanconfig }, { "clear", chanconfig }, { "unused", chanconfig }, + { "cas", chanconfig }, + { "user", chanconfig }, { "alaw", setlaw }, { "mulaw", setlaw }, { "deflaw", setlaw }, |