ixj-REDHAT.c
上传用户:sy_wanhua
上传日期:2013-07-25
资源大小:3048k
文件大小:237k
- /**
- * Redhat Modifications Note:
- * lines that look like:
- * 'kill_fasync(j->async_queue, SIGIO);'
- * had to be changed to:
- * 'kill_fasync(ixj[board].async_queue, SIGIO, POLL_IN);'
- * since RedHat has introduced proprietary modifications
- * into the linux kernel. Contact www.quicknet.com or
- * www.redhat.com for details.
- */
- /****************************************************************************
- * ixj.c
- *
- * Device Driver for the Internet PhoneJACK and
- * Internet LineJACK Telephony Cards.
- *
- * (c) Copyright 1999-2000 Quicknet Technologies, Inc.
- *
- * 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.
- *
- * Author: Ed Okerson, <eokerson@quicknet.net>
- *
- * Contributors: Greg Herlein, <gherlein@quicknet.net>
- * David W. Erhart, <derhart@quicknet.net>
- * John Sellers, <jsellers@quicknet.net>
- * Mike Preston, <mpreston@quicknet.net>
- *
- * Fixes:
- *
- * More information about the hardware related to this driver can be found
- * at our website: http://www.quicknet.net
- *
- * IN NO EVENT SHALL QUICKNET TECHNOLOGIES, INC. BE LIABLE TO ANY PARTY FOR
- * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
- * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF QUICKNET
- * TECHNOLOGIES, INC.HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- * QUICKNET TECHNOLOGIES, INC. SPECIFICALLY DISCLAIMS ANY WARRANTIES,
- * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
- * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
- * ON AN "AS IS" BASIS, AND QUICKNET TECHNOLOGIES, INC. HAS NO OBLIGATION
- * TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
- *
- ***************************************************************************/
- static char ixj_c_rcsid[] = "$Id: ixj-REDHAT.c,v 1.1 2001/02/05 20:22:23 zolli Exp $";
- //#define PERFMON_STATS
- #define IXJDEBUG 0
- #define MAXRINGS 5
- #include <linux/autoconf.h>
- #if defined(CONFIG_MODVERSIONS) && !defined(MODVERSIONS)
- #define MODVERSIONS
- #endif
- #ifdef MODVERSIONS
- #include <linux/modversions.h>
- #endif
- #ifdef CONFIG_PCMCIA
- #include <pcmcia/config.h>
- #include <pcmcia/k_compat.h>
- #endif
- #include <linux/module.h>
- #include <linux/init.h>
- #include <linux/sched.h>
- #include <linux/kernel.h> /* printk() */
- #include <linux/fs.h> /* everything... */
- #include <linux/errno.h> /* error codes */
- #include <linux/malloc.h>
- #include <linux/mm.h>
- #include <linux/ioport.h>
- #include <linux/interrupt.h>
- #include <linux/tqueue.h>
- #include <linux/proc_fs.h>
- #include <linux/poll.h>
- #include <linux/timer.h>
- #include <linux/delay.h>
- #include <linux/pci.h>
- #include <asm/io.h>
- #include <asm/segment.h>
- #include <asm/uaccess.h>
- #ifdef CONFIG_ISAPNP
- #include "../isapnp/pnpio.h"
- #include "../isapnp/isapnp.h"
- #endif
- #ifdef CONFIG_PCMCIA
- #include <pcmcia/version.h>
- #include <pcmcia/cs_types.h>
- #include <pcmcia/cs.h>
- #include <pcmcia/cistpl.h>
- #include <pcmcia/ds.h>
- #include <pcmcia/cisreg.h>
- #include <pcmcia/ciscode.h>
- #endif
- #include "ixj.h"
- #define TYPE(dev) (MINOR(dev) >> 4)
- #define NUM(dev) (MINOR(dev) & 0xf)
- static int ixjdebug = 0;
- static int hertz = HZ;
- static int samplerate = 100;
- MODULE_PARM(ixjdebug, "i");
- static IXJ ixj[IXJMAX];
- static struct timer_list ixj_timer;
- int ixj_convert_loaded = 0;
- /************************************************************************
- *
- * These are function definitions to allow external modules to register
- * enhanced functionality call backs.
- *
- ************************************************************************/
- static int Stub(IXJ * J, unsigned long arg)
- {
- return 0;
- }
- static IXJ_REGFUNC ixj_DownloadG729 = &Stub;
- static IXJ_REGFUNC ixj_DownloadTS85 = &Stub;
- static IXJ_REGFUNC ixj_PreRead = &Stub;
- static IXJ_REGFUNC ixj_PostRead = &Stub;
- static IXJ_REGFUNC ixj_PreWrite = &Stub;
- static IXJ_REGFUNC ixj_PostWrite = &Stub;
- static IXJ_REGFUNC ixj_PreIoctl = &Stub;
- static IXJ_REGFUNC ixj_PostIoctl = &Stub;
- static void ixj_read_frame(int board);
- static void ixj_write_frame(int board);
- static void ixj_init_timer(void);
- static void ixj_add_timer(void);
- static void ixj_del_timer(void);
- static void ixj_timeout(unsigned long ptr);
- static int read_filters(int board);
- static int LineMonitor(int board);
- static int ixj_fasync(int fd, struct file *, int mode);
- static int ixj_hookstate(int board);
- static int ixj_record_start(int board);
- static void ixj_record_stop(int board);
- static void ixj_vad(int board, int arg);
- static int ixj_play_start(int board);
- static void ixj_play_stop(int board);
- static int ixj_set_tone_on(unsigned short arg, int board);
- static int ixj_set_tone_off(unsigned short, int board);
- static int ixj_play_tone(int board, char tone);
- static int idle(int board);
- static void ixj_ring_on(int board);
- static void ixj_ring_off(int board);
- static void aec_stop(int board);
- static void ixj_ringback(int board);
- static void ixj_busytone(int board);
- static void ixj_dialtone(int board);
- static void ixj_cpt_stop(int board);
- static char daa_int_read(int board);
- static int daa_set_mode(int board, int mode);
- static int ixj_linetest(int board);
- static int ixj_daa_cid_read(int board);
- static void DAA_Coeff_US(int board);
- static void DAA_Coeff_UK(int board);
- static void DAA_Coeff_France(int board);
- static void DAA_Coeff_Germany(int board);
- static void DAA_Coeff_Australia(int board);
- static void DAA_Coeff_Japan(int board);
- static int ixj_init_filter(int board, IXJ_FILTER * jf);
- static int ixj_init_tone(int board, IXJ_TONE * ti);
- static int ixj_build_cadence(int board, IXJ_CADENCE * cp);
- static int ixj_build_filter_cadence(int board, IXJ_FILTER_CADENCE * cp);
- // Serial Control Interface funtions
- static int SCI_Control(int board, int control);
- static int SCI_Prepare(int board);
- static int SCI_WaitHighSCI(int board);
- static int SCI_WaitLowSCI(int board);
- static DWORD PCIEE_GetSerialNumber(WORD wAddress);
- /************************************************************************
- CT8020/CT8021 Host Programmers Model
- Host address Function Access
- DSPbase +
- 0-1 Aux Software Status Register (reserved) Read Only
- 2-3 Software Status Register Read Only
- 4-5 Aux Software Control Register (reserved) Read Write
- 6-7 Software Control Register Read Write
- 8-9 Hardware Status Register Read Only
- A-B Hardware Control Register Read Write
- C-D Host Transmit (Write) Data Buffer Access Port (buffer input)Write Only
- E-F Host Recieve (Read) Data Buffer Access Port (buffer input) Read Only
- ************************************************************************/
- extern __inline__ void ixj_read_HSR(int board)
- {
- ixj[board].hsr.bytes.low = inb_p(ixj[board].DSPbase + 8);
- ixj[board].hsr.bytes.high = inb_p(ixj[board].DSPbase + 9);
- }
- extern __inline__ int IsControlReady(int board)
- {
- ixj_read_HSR(board);
- return ixj[board].hsr.bits.controlrdy ? 1 : 0;
- }
- extern __inline__ int IsPCControlReady(int board)
- {
- ixj[board].pccr1.byte = inb_p(ixj[board].XILINXbase + 3);
- return ixj[board].pccr1.bits.crr ? 1 : 0;
- }
- extern __inline__ int IsStatusReady(int board)
- {
- ixj_read_HSR(board);
- return ixj[board].hsr.bits.statusrdy ? 1 : 0;
- }
- extern __inline__ int IsRxReady(int board)
- {
- ixj_read_HSR(board);
- return ixj[board].hsr.bits.rxrdy ? 1 : 0;
- }
- extern __inline__ int IsTxReady(int board)
- {
- ixj_read_HSR(board);
- return ixj[board].hsr.bits.txrdy ? 1 : 0;
- }
- extern __inline__ BYTE SLIC_GetState(int board)
- {
- IXJ *j = &ixj[board];
- j->pld_slicr.byte = inb_p(j->XILINXbase + 0x01);
- return j->pld_slicr.bits.state;
- }
- static BOOL SLIC_SetState(BYTE byState, int board)
- {
- BOOL fRetVal = FALSE;
- IXJ *j = &ixj[board];
- // Set the C1, C2, C3 & B2EN signals.
- switch (byState) {
- case PLD_SLIC_STATE_OC:
- j->pld_slicw.bits.c1 = 0;
- j->pld_slicw.bits.c2 = 0;
- j->pld_slicw.bits.c3 = 0;
- j->pld_slicw.bits.b2en = 0;
- outb_p(j->pld_slicw.byte, j->XILINXbase + 0x01);
- fRetVal = TRUE;
- break;
- case PLD_SLIC_STATE_RINGING:
- j->pld_slicw.bits.c1 = 1;
- j->pld_slicw.bits.c2 = 0;
- j->pld_slicw.bits.c3 = 0;
- j->pld_slicw.bits.b2en = 1;
- outb_p(j->pld_slicw.byte, j->XILINXbase + 0x01);
- fRetVal = TRUE;
- break;
- case PLD_SLIC_STATE_ACTIVE:
- j->pld_slicw.bits.c1 = 0;
- j->pld_slicw.bits.c2 = 1;
- j->pld_slicw.bits.c3 = 0;
- j->pld_slicw.bits.b2en = 0;
- outb_p(j->pld_slicw.byte, j->XILINXbase + 0x01);
- fRetVal = TRUE;
- break;
- case PLD_SLIC_STATE_OHT: // On-hook transmit
- j->pld_slicw.bits.c1 = 1;
- j->pld_slicw.bits.c2 = 1;
- j->pld_slicw.bits.c3 = 0;
- j->pld_slicw.bits.b2en = 0;
- outb_p(j->pld_slicw.byte, j->XILINXbase + 0x01);
- fRetVal = TRUE;
- break;
- case PLD_SLIC_STATE_TIPOPEN:
- j->pld_slicw.bits.c1 = 0;
- j->pld_slicw.bits.c2 = 0;
- j->pld_slicw.bits.c3 = 1;
- j->pld_slicw.bits.b2en = 0;
- outb_p(j->pld_slicw.byte, j->XILINXbase + 0x01);
- fRetVal = TRUE;
- break;
- case PLD_SLIC_STATE_STANDBY:
- j->pld_slicw.bits.c1 = 1;
- j->pld_slicw.bits.c2 = 0;
- j->pld_slicw.bits.c3 = 1;
- j->pld_slicw.bits.b2en = 1;
- outb_p(j->pld_slicw.byte, j->XILINXbase + 0x01);
- fRetVal = TRUE;
- break;
- case PLD_SLIC_STATE_APR: // Active polarity reversal
- j->pld_slicw.bits.c1 = 0;
- j->pld_slicw.bits.c2 = 1;
- j->pld_slicw.bits.c3 = 1;
- j->pld_slicw.bits.b2en = 0;
- outb_p(j->pld_slicw.byte, j->XILINXbase + 0x01);
- fRetVal = TRUE;
- break;
- case PLD_SLIC_STATE_OHTPR: // OHT polarity reversal
- j->pld_slicw.bits.c1 = 1;
- j->pld_slicw.bits.c2 = 1;
- j->pld_slicw.bits.c3 = 1;
- j->pld_slicw.bits.b2en = 0;
- outb_p(j->pld_slicw.byte, j->XILINXbase + 0x01);
- fRetVal = TRUE;
- break;
- default:
- fRetVal = FALSE;
- break;
- }
- return fRetVal;
- }
- int ixj_register(int index, IXJ_REGFUNC regfunc)
- {
- int cnt;
- int retval = 0;
- switch (index) {
- case G729LOADER:
- ixj_DownloadG729 = regfunc;
- for (cnt = 0; cnt < IXJMAX; cnt++)
- ixj_DownloadG729(&ixj[cnt], 0L);
- break;
- case TS85LOADER:
- ixj_DownloadTS85 = regfunc;
- for (cnt = 0; cnt < IXJMAX; cnt++)
- ixj_DownloadTS85(&ixj[cnt], 0L);
- break;
- case PRE_READ:
- ixj_PreRead = regfunc;
- break;
- case POST_READ:
- ixj_PostRead = regfunc;
- break;
- case PRE_WRITE:
- ixj_PreWrite = regfunc;
- break;
- case POST_WRITE:
- ixj_PostWrite = regfunc;
- break;
- case PRE_IOCTL:
- ixj_PreIoctl = regfunc;
- break;
- case POST_IOCTL:
- ixj_PostIoctl = regfunc;
- break;
- default:
- retval = 1;
- }
- return retval;
- }
- int ixj_unregister(int index)
- {
- int retval = 0;
- switch (index) {
- case G729LOADER:
- ixj_DownloadG729 = &Stub;
- break;
- case TS85LOADER:
- ixj_DownloadTS85 = &Stub;
- break;
- case PRE_READ:
- ixj_PreRead = &Stub;
- break;
- case POST_READ:
- ixj_PostRead = &Stub;
- break;
- case PRE_WRITE:
- ixj_PreWrite = &Stub;
- break;
- case POST_WRITE:
- ixj_PostWrite = &Stub;
- break;
- case PRE_IOCTL:
- ixj_PreIoctl = &Stub;
- break;
- case POST_IOCTL:
- ixj_PostIoctl = &Stub;
- break;
- default:
- retval = 1;
- }
- return retval;
- }
- static void ixj_init_timer(void)
- {
- init_timer(&ixj_timer);
- ixj_timer.function = ixj_timeout;
- ixj_timer.data = (int) NULL;
- }
- static void ixj_add_timer(void)
- {
- ixj_timer.expires = jiffies + (hertz / samplerate);
- add_timer(&ixj_timer);
- }
- static void ixj_del_timer(void)
- {
- del_timer(&ixj_timer);
- }
- static void ixj_tone_timeout(int board)
- {
- IXJ *j = &ixj[board];
- IXJ_TONE ti;
- j->tone_state++;
- if (j->tone_state == 3) {
- j->tone_state = 0;
- if (j->cadence_t) {
- j->tone_cadence_state++;
- if (j->tone_cadence_state >= j->cadence_t->elements_used) {
- switch (j->cadence_t->termination) {
- case PLAY_ONCE:
- ixj_cpt_stop(board);
- break;
- case REPEAT_LAST_ELEMENT:
- j->tone_cadence_state--;
- ixj_play_tone(board, j->cadence_t->ce[j->tone_cadence_state].index);
- break;
- case REPEAT_ALL:
- j->tone_cadence_state = 0;
- if (j->cadence_t->ce[j->tone_cadence_state].freq0) {
- ti.tone_index = j->cadence_t->ce[j->tone_cadence_state].index;
- ti.freq0 = j->cadence_t->ce[j->tone_cadence_state].freq0;
- ti.gain0 = j->cadence_t->ce[j->tone_cadence_state].gain0;
- ti.freq1 = j->cadence_t->ce[j->tone_cadence_state].freq1;
- ti.gain1 = j->cadence_t->ce[j->tone_cadence_state].gain1;
- ixj_init_tone(board, &ti);
- }
- ixj_set_tone_on(j->cadence_t->ce[0].tone_on_time, board);
- ixj_set_tone_off(j->cadence_t->ce[0].tone_off_time, board);
- ixj_play_tone(board, j->cadence_t->ce[0].index);
- break;
- }
- } else {
- if (j->cadence_t->ce[j->tone_cadence_state].gain0) {
- ti.tone_index = j->cadence_t->ce[j->tone_cadence_state].index;
- ti.freq0 = j->cadence_t->ce[j->tone_cadence_state].freq0;
- ti.gain0 = j->cadence_t->ce[j->tone_cadence_state].gain0;
- ti.freq1 = j->cadence_t->ce[j->tone_cadence_state].freq1;
- ti.gain1 = j->cadence_t->ce[j->tone_cadence_state].gain1;
- ixj_init_tone(board, &ti);
- }
- ixj_set_tone_on(j->cadence_t->ce[j->tone_cadence_state].tone_on_time, board);
- ixj_set_tone_off(j->cadence_t->ce[j->tone_cadence_state].tone_off_time, board);
- ixj_play_tone(board, j->cadence_t->ce[j->tone_cadence_state].index);
- }
- }
- }
- }
- static void ixj_timeout(unsigned long ptr)
- {
- int board;
- unsigned long jifon;
- IXJ *j;
- for (board = 0; board < IXJMAX; board++) {
- j = &ixj[board];
- if (j->DSPbase) {
- #ifdef PERFMON_STATS
- j->timerchecks++;
- #endif
- if (j->tone_state) {
- if (!ixj_hookstate(board)) {
- ixj_cpt_stop(board);
- if (j->m_hook) {
- j->m_hook = 0;
- j->ex.bits.hookstate = 1;
- if (j->async_queue)
- {
- kill_fasync(ixj[board].async_queue, SIGIO, POLL_IN);
- }
- }
- continue;
- }
- if (j->tone_state == 1)
- jifon = (hertz * j->tone_on_time * 25 / 100000);
- else
- jifon = (hertz * j->tone_on_time * 25 / 100000) +
- (hertz * j->tone_off_time * 25 / 100000);
- if (time_before(jiffies, j->tone_start_jif + jifon)) {
- if (j->tone_state == 1) {
- ixj_play_tone(board, j->tone_index);
- if (j->dsp.low == 0x20) {
- continue;
- }
- } else {
- ixj_play_tone(board, 0);
- if (j->dsp.low == 0x20) {
- continue;
- }
- }
- } else {
- ixj_tone_timeout(board);
- if (j->flags.dialtone) {
- ixj_dialtone(board);
- }
- if (j->flags.busytone) {
- ixj_busytone(board);
- if (j->dsp.low == 0x20) {
- continue;
- }
- }
- if (j->flags.ringback) {
- ixj_ringback(board);
- if (j->dsp.low == 0x20) {
- continue;
- }
- }
- if (!j->tone_state) {
- if (j->dsp.low == 0x20 || (j->play_mode == -1 && j->rec_mode == -1))
- idle(board);
- if (j->dsp.low == 0x20 && j->play_mode != -1)
- ixj_play_start(board);
- if (j->dsp.low == 0x20 && j->rec_mode != -1)
- ixj_record_start(board);
- }
- }
- }
- if (!j->tone_state || j->dsp.low != 0x20) {
- if (IsRxReady(board)) {
- ixj_read_frame(board);
- }
- if (IsTxReady(board)) {
- ixj_write_frame(board);
- }
- }
- if (j->flags.cringing) {
- if (ixj_hookstate(board) & 1) {
- j->flags.cringing = 0;
- ixj_ring_off(board);
- } else {
- if (jiffies - j->ring_cadence_jif >= (.5 * hertz)) {
- j->ring_cadence_t--;
- if (j->ring_cadence_t == -1)
- j->ring_cadence_t = 15;
- j->ring_cadence_jif = jiffies;
- }
- if (j->ring_cadence & 1 << j->ring_cadence_t) {
- ixj_ring_on(board);
- } else {
- ixj_ring_off(board);
- }
- continue;
- }
- }
- if (!j->flags.ringing) {
- if (ixj_hookstate(board)) {
- if (j->dsp.low != 0x20 &&
- j->pld_slicr.bits.state != PLD_SLIC_STATE_ACTIVE)
- // Internet LineJACK
- {
- SLIC_SetState(PLD_SLIC_STATE_ACTIVE, board);
- }
- LineMonitor(board);
- read_filters(board);
- ixj_WriteDSPCommand(0x511B, board);
- j->proc_load = j->ssr.high << 8 | j->ssr.low;
- if (!j->m_hook) {
- j->m_hook = j->ex.bits.hookstate = 1;
- if (j->async_queue)
- kill_fasync(ixj[board].async_queue, SIGIO, POLL_IN);
- }
- } else {
- if (j->dsp.low != 0x20 &&
- j->pld_slicr.bits.state == PLD_SLIC_STATE_ACTIVE)
- // Internet LineJACK
- {
- SLIC_SetState(PLD_SLIC_STATE_STANDBY, board);
- }
- if (j->ex.bits.dtmf_ready) {
- j->dtmf_wp = j->dtmf_rp = j->ex.bits.dtmf_ready = 0;
- }
- if (j->m_hook) {
- j->m_hook = 0;
- j->ex.bits.hookstate = 1;
- if (j->async_queue)
- kill_fasync(ixj[board].async_queue, SIGIO, POLL_IN);
- }
- }
- }
- if (j->cardtype == 300) {
- if (j->flags.pstn_present) {
- j->pld_scrr.byte = inb_p(j->XILINXbase);
- if (jiffies >= j->pstn_sleeptil && j->pld_scrr.bits.daaflag) {
- daa_int_read(board);
- if (j->m_DAAShadowRegs.XOP_REGS.XOP.xr0.bitreg.RING) {
- if (!j->flags.pstn_ringing) {
- j->flags.pstn_ringing = 1;
- if (j->daa_mode != SOP_PU_RINGING)
- daa_set_mode(board, SOP_PU_RINGING);
- }
- }
- if (j->m_DAAShadowRegs.XOP_REGS.XOP.xr0.bitreg.VDD_OK) {
- j->pstn_winkstart = 0;
- if (j->flags.pstn_ringing && !j->pstn_envelope) {
- j->ex.bits.pstn_ring = 0;
- j->pstn_envelope = 1;
- j->pstn_ring_start = jiffies;
- }
- } else {
- if (j->flags.pstn_ringing && j->pstn_envelope &&
- jiffies > j->pstn_ring_start + ((hertz * 15) / 10)) {
- j->ex.bits.pstn_ring = 1;
- j->pstn_envelope = 0;
- } else if (j->daa_mode == SOP_PU_CONVERSATION) {
- if (!j->pstn_winkstart) {
- j->pstn_winkstart = jiffies;
- } else if (jiffies > j->pstn_winkstart + (hertz * j->winktime / 1000)) {
- daa_set_mode(board, SOP_PU_SLEEP);
- j->pstn_winkstart = 0;
- j->ex.bits.pstn_wink = 1;
- }
- } else {
- j->ex.bits.pstn_ring = 0;
- }
- }
- if (j->m_DAAShadowRegs.XOP_REGS.XOP.xr0.bitreg.Cadence) {
- if (j->daa_mode == SOP_PU_RINGING) {
- daa_set_mode(board, SOP_PU_SLEEP);
- j->flags.pstn_ringing = 0;
- j->ex.bits.pstn_ring = 0;
- }
- }
- if (j->m_DAAShadowRegs.XOP_REGS.XOP.xr0.bitreg.Caller_ID) {
- if (j->daa_mode == SOP_PU_RINGING && j->flags.pstn_ringing) {
- j->pstn_cid_intr = 1;
- j->pstn_cid_recieved = jiffies;
- }
- }
- } else {
- if (j->pld_scrr.bits.daaflag) {
- daa_int_read(board);
- }
- j->ex.bits.pstn_ring = 0;
- if (j->pstn_cid_intr && jiffies > j->pstn_cid_recieved + (hertz * 3)) {
- if (j->daa_mode == SOP_PU_RINGING) {
- ixj_daa_cid_read(board);
- j->ex.bits.caller_id = 1;
- }
- j->pstn_cid_intr = 0;
- } else {
- j->ex.bits.caller_id = 0;
- }
- if (!j->m_DAAShadowRegs.XOP_REGS.XOP.xr0.bitreg.VDD_OK) {
- if (j->flags.pstn_ringing && j->pstn_envelope) {
- j->ex.bits.pstn_ring = 1;
- j->pstn_envelope = 0;
- } else if (j->daa_mode == SOP_PU_CONVERSATION) {
- if (!j->pstn_winkstart) {
- j->pstn_winkstart = jiffies;
- } else if (jiffies > j->pstn_winkstart + (hertz * 320 / 1000)) {
- daa_set_mode(board, SOP_PU_SLEEP);
- j->pstn_winkstart = 0;
- j->ex.bits.pstn_wink = 1;
- }
- }
- }
- }
- }
- }
- if (j->ex.bytes) {
- wake_up_interruptible(&j->poll_q); // Wake any blocked selects
- if (j->async_queue)
- kill_fasync(ixj[board].async_queue, SIGIO, POLL_IN);
- }
- } else {
- break;
- }
- }
- ixj_add_timer();
- }
- static int ixj_status_wait(int board)
- {
- unsigned long jif;
- jif = jiffies;
- while (!IsStatusReady(board)) {
- if (jiffies - jif > (60 * (hertz / 100))) {
- return -1;
- }
- }
- return 0;
- }
- static int ixj_PCcontrol_wait(int board)
- {
- unsigned long jif;
- jif = jiffies;
- while (!IsPCControlReady(board)) {
- if (jiffies - jif > (60 * (hertz / 100))) {
- return -1;
- }
- }
- return 0;
- }
- int ixj_WriteDSPCommand(unsigned short cmd, int board)
- {
- BYTES bytes;
- unsigned long jif;
- bytes.high = (cmd & 0xFF00) >> 8;
- bytes.low = cmd & 0x00FF;
- jif = jiffies;
- while (!IsControlReady(board)) {
- if (jiffies - jif > (60 * (hertz / 100))) {
- return -1;
- }
- }
- outb_p(bytes.low, ixj[board].DSPbase + 6);
- outb_p(bytes.high, ixj[board].DSPbase + 7);
- if (ixj_status_wait(board)) {
- ixj[board].ssr.low = 0xFF;
- ixj[board].ssr.high = 0xFF;
- return -1;
- }
- /* Read Software Status Register */
- ixj[board].ssr.low = inb_p(ixj[board].DSPbase + 2);
- ixj[board].ssr.high = inb_p(ixj[board].DSPbase + 3);
- return 0;
- }
- /***************************************************************************
- *
- * General Purpose IO Register read routine
- *
- ***************************************************************************/
- extern __inline__ int ixj_gpio_read(int board)
- {
- if (ixj_WriteDSPCommand(0x5143, board))
- return -1;
- ixj[board].gpio.bytes.low = ixj[board].ssr.low;
- ixj[board].gpio.bytes.high = ixj[board].ssr.high;
- return 0;
- }
- extern __inline__ void LED_SetState(int state, int board)
- {
- if (ixj[board].cardtype == 300) {
- ixj[board].pld_scrw.bits.led1 = state & 0x1 ? 1 : 0;
- ixj[board].pld_scrw.bits.led2 = state & 0x2 ? 1 : 0;
- ixj[board].pld_scrw.bits.led3 = state & 0x4 ? 1 : 0;
- ixj[board].pld_scrw.bits.led4 = state & 0x8 ? 1 : 0;
- outb_p(ixj[board].pld_scrw.byte, ixj[board].XILINXbase);
- }
- }
- /*********************************************************************
- * GPIO Pins are configured as follows on the Quicknet Internet
- * PhoneJACK Telephony Cards
- *
- * POTS Select GPIO_6=0 GPIO_7=0
- * Mic/Speaker Select GPIO_6=0 GPIO_7=1
- * Handset Select GPIO_6=1 GPIO_7=0
- *
- * SLIC Active GPIO_1=0 GPIO_2=1 GPIO_5=0
- * SLIC Ringing GPIO_1=1 GPIO_2=1 GPIO_5=0
- * SLIC Open Circuit GPIO_1=0 GPIO_2=0 GPIO_5=0
- *
- * Hook Switch changes reported on GPIO_3
- *********************************************************************/
- static int ixj_set_port(int board, int arg)
- {
- IXJ *j = &ixj[board];
- if (j->cardtype == 400) {
- if (arg != PORT_POTS)
- return 10;
- else
- return 0;
- }
- if (j->cardtype == 600) {
- if (arg != PORT_SPEAKER)
- return 11;
- else
- return 0;
- }
- switch (arg) {
- case PORT_POTS:
- j->port = PORT_POTS;
- switch (j->cardtype) {
- case 500:
- j->pld_slicw.pcib.mic = 0;
- j->pld_slicw.pcib.spk = 0;
- outb_p(j->pld_slicw.byte, j->XILINXbase + 0x01);
- break;
- case 300:
- if (ixj_WriteDSPCommand(0xC528, board)) /* Write CODEC config to
- Software Control Register */
- return 2;
- j->pld_scrw.bits.daafsyncen = 0; // Turn off DAA Frame Sync
- outb_p(j->pld_scrw.byte, j->XILINXbase);
- j->pld_clock.byte = 0;
- outb_p(j->pld_clock.byte, j->XILINXbase + 0x04);
- j->pld_slicw.bits.rly1 = 1;
- j->pld_slicw.bits.spken = 0;
- outb_p(j->pld_slicw.byte, j->XILINXbase + 0x01);
- SLIC_SetState(PLD_SLIC_STATE_STANDBY, board);
- break;
- case 100:
- j->gpio.bytes.high = 0x0B;
- j->gpio.bits.gpio6 = 0;
- j->gpio.bits.gpio7 = 0;
- ixj_WriteDSPCommand(j->gpio.word, board);
- break;
- }
- break;
- case PORT_PSTN:
- if (j->cardtype == 300) {
- ixj_WriteDSPCommand(0xC534, board); /* Write CODEC config to Software Control Register */
- j->pld_slicw.bits.rly3 = 0;
- j->pld_slicw.bits.rly1 = 1;
- j->pld_slicw.bits.spken = 0;
- outb_p(j->pld_slicw.byte, j->XILINXbase + 0x01);
- j->port = PORT_PSTN;
- } else {
- return 4;
- }
- break;
- case PORT_SPEAKER:
- j->port = PORT_SPEAKER;
- switch (j->cardtype) {
- case 500:
- j->pld_slicw.pcib.mic = 1;
- j->pld_slicw.pcib.spk = 1;
- outb_p(j->pld_slicw.byte, j->XILINXbase + 0x01);
- break;
- case 600:
- case 300:
- break;
- case 100:
- j->gpio.bytes.high = 0x0B;
- j->gpio.bits.gpio6 = 0;
- j->gpio.bits.gpio7 = 1;
- ixj_WriteDSPCommand(j->gpio.word, board);
- break;
- }
- break;
- case PORT_HANDSET:
- if (j->cardtype == 300 || j->cardtype == 500) {
- return 5;
- } else {
- j->gpio.bytes.high = 0x0B;
- j->gpio.bits.gpio6 = 1;
- j->gpio.bits.gpio7 = 0;
- ixj_WriteDSPCommand(j->gpio.word, board);
- j->port = PORT_HANDSET;
- }
- break;
- default:
- return 6;
- break;
- }
- return 0;
- }
- static int ixj_set_pots(int board, int arg)
- {
- IXJ *j = &ixj[board];
- if (j->cardtype == 300) {
- if (arg) {
- if (j->port == PORT_PSTN) {
- j->pld_slicw.bits.rly1 = 0;
- outb_p(j->pld_slicw.byte, j->XILINXbase + 0x01);
- return 1;
- } else {
- return 0;
- }
- } else {
- j->pld_slicw.bits.rly1 = 1;
- outb_p(j->pld_slicw.byte, j->XILINXbase + 0x01);
- return 1;
- }
- } else {
- return 0;
- }
- }
- static void ixj_ring_on(int board)
- {
- IXJ *j = &ixj[board];
- if (j->dsp.low == 0x20) // Internet PhoneJACK
- {
- if (ixjdebug > 0)
- printk(KERN_INFO "IXJ Ring On /dev/phone%dn", board);
- j->gpio.bytes.high = 0x0B;
- j->gpio.bytes.low = 0x00;
- j->gpio.bits.gpio1 = 1;
- j->gpio.bits.gpio2 = 1;
- j->gpio.bits.gpio5 = 0;
- ixj_WriteDSPCommand(j->gpio.word, board); /* send the ring signal */
- } else // Internet LineJACK, Internet PhoneJACK Lite or
- // Internet PhoneJACK PCI
- {
- if (ixjdebug > 0)
- printk(KERN_INFO "IXJ Ring On /dev/phone%dn", board);
- SLIC_SetState(PLD_SLIC_STATE_RINGING, board);
- }
- }
- static int ixj_pcmcia_cable_check(int board)
- {
- IXJ *j = &ixj[board];
- j->pccr1.byte = inb_p(j->XILINXbase + 0x03);
- if (!j->pccr1.bits.drf) {
- j->psccr.bits.dev = 3;
- j->psccr.bits.rw = 1;
- outb(j->psccr.byte, j->XILINXbase + 0x01);
- if (ixj_PCcontrol_wait(board))
- return 0;
- else {
- if (!j->flags.pcmciascp) {
- j->flags.pcmciascp = 1; // Set Cable Present Flag
- j->flags.pcmciasct = inb_p(j->XILINXbase + 0x01); // Get Cable Type
- j->sic1.bits.cpd = 0; // Chip Power Down
- j->sic1.bits.mpd = 0; // MIC Bias Power Down
- j->sic1.bits.hpd = 0; // Handset Bias Power Down
- j->sic1.bits.lpd = 0; // Line Bias Power Down
- j->sic1.bits.spd = 1; // Speaker Drive Power Down
- j->psccr.bits.addr = 1; // R/W Smart Cable Register Address
- j->psccr.bits.rw = 0; // Read / Write flag
- j->psccr.bits.dev = 0;
- outb(j->sic1.byte, j->XILINXbase + 0x00);
- outb(j->psccr.byte, j->XILINXbase + 0x01);
- ixj_PCcontrol_wait(board);
- j->sic2.bits.al = 0; // Analog Loopback DAC analog -> ADC analog
- j->sic2.bits.dl2 = 0; // Digital Loopback DAC -> ADC one bit
- j->sic2.bits.dl1 = 0; // Digital Loopback ADC -> DAC one bit
- j->sic2.bits.pll = 0; // 1 = div 10, 0 = div 5
- j->sic2.bits.hpd = 0; // HPF disable
- j->psccr.bits.addr = 2; // R/W Smart Cable Register Address
- j->psccr.bits.rw = 0; // Read / Write flag
- j->psccr.bits.dev = 0;
- outb(j->sic2.byte, j->XILINXbase + 0x00);
- outb(j->psccr.byte, j->XILINXbase + 0x01);
- ixj_PCcontrol_wait(board);
- j->psccr.bits.addr = 3; // R/W Smart Cable Register Address
- j->psccr.bits.rw = 0; // Read / Write flag
- j->psccr.bits.dev = 0;
- outb(0x00, j->XILINXbase + 0x00); // PLL Divide N1
- outb(j->psccr.byte, j->XILINXbase + 0x01);
- ixj_PCcontrol_wait(board);
- j->psccr.bits.addr = 4; // R/W Smart Cable Register Address
- j->psccr.bits.rw = 0; // Read / Write flag
- j->psccr.bits.dev = 0;
- outb(0x09, j->XILINXbase + 0x00); // PLL Multiply M1
- outb(j->psccr.byte, j->XILINXbase + 0x01);
- ixj_PCcontrol_wait(board);
- j->sirxg.bits.lig = 1; // Line In Gain
- j->sirxg.bits.lim = 1; // Line In Mute
- j->sirxg.bits.mcg = 3; // MIC In Gain
- j->sirxg.bits.mcm = 0; // MIC In Mute
- j->sirxg.bits.him = 0; // Handset In Mute
- j->sirxg.bits.iir = 1; // IIR
- j->psccr.bits.addr = 5; // R/W Smart Cable Register Address
- j->psccr.bits.rw = 0; // Read / Write flag
- j->psccr.bits.dev = 0;
- outb(j->sirxg.byte, j->XILINXbase + 0x00);
- outb(j->psccr.byte, j->XILINXbase + 0x01);
- ixj_PCcontrol_wait(board);
- j->siadc.bits.hom = 0; // Handset Out Mute
- j->siadc.bits.lom = 0; // Line Out Mute
- j->siadc.bits.rxg = (0xC000 - 0x41C8) / 0x4EF; // RX PGA Gain
- j->psccr.bits.addr = 6; // R/W Smart Cable Register Address
- j->psccr.bits.rw = 0; // Read / Write flag
- j->psccr.bits.dev = 0;
- outb(j->siadc.byte, j->XILINXbase + 0x00);
- outb(j->psccr.byte, j->XILINXbase + 0x01);
- ixj_PCcontrol_wait(board);
- j->sidac.bits.srm = 1; // Speaker Right Mute
- j->sidac.bits.slm = 1; // Speaker Left Mute
- j->sidac.bits.txg = (0xC000 - 0x45E4) / 0x5D3; // TX PGA Gain
- j->psccr.bits.addr = 7; // R/W Smart Cable Register Address
- j->psccr.bits.rw = 0; // Read / Write flag
- j->psccr.bits.dev = 0;
- outb(j->sidac.byte, j->XILINXbase + 0x00);
- outb(j->psccr.byte, j->XILINXbase + 0x01);
- ixj_PCcontrol_wait(board);
- j->siaatt.bits.sot = 0;
- j->psccr.bits.addr = 9; // R/W Smart Cable Register Address
- j->psccr.bits.rw = 0; // Read / Write flag
- j->psccr.bits.dev = 0;
- outb(j->siaatt.byte, j->XILINXbase + 0x00);
- outb(j->psccr.byte, j->XILINXbase + 0x01);
- ixj_PCcontrol_wait(board);
- }
- }
- return 1;
- } else {
- j->flags.pcmciascp = 0;
- return 0;
- }
- }
- static int ixj_hookstate(int board)
- {
- unsigned long det;
- IXJ *j = &ixj[board];
- int fOffHook = 0;
- switch (j->cardtype) {
- case 100:
- ixj_gpio_read(board);
- fOffHook = j->gpio.bits.gpio3read ? 1 : 0;
- break;
- case 300:
- case 400:
- case 500:
- SLIC_GetState(board);
- if (j->pld_slicr.bits.state == PLD_SLIC_STATE_ACTIVE ||
- j->pld_slicr.bits.state == PLD_SLIC_STATE_STANDBY) {
- if (j->flags.ringing) {
- if (!in_interrupt()) {
- det = jiffies + (hertz / 50);
- while (time_before(jiffies, det)) {
- current->state = TASK_INTERRUPTIBLE;
- schedule_timeout(1);
- }
- }
- SLIC_GetState(board);
- if (j->pld_slicr.bits.state == PLD_SLIC_STATE_RINGING) {
- ixj_ring_on(board);
- }
- }
- if (j->cardtype == 500) {
- j->pld_scrr.byte = inb_p(j->XILINXbase);
- fOffHook = j->pld_scrr.pcib.det ? 1 : 0;
- } else
- fOffHook = j->pld_slicr.bits.det ? 1 : 0;
- }
- break;
- case 600:
- fOffHook = ixj_pcmcia_cable_check(board);
- break;
- }
- if (j->r_hook != fOffHook) {
- j->r_hook = fOffHook;
- if (j->port != PORT_POTS || j->cardtype == 600) {
- j->ex.bits.hookstate = 1;
- if (j->async_queue)
- kill_fasync(ixj[board].async_queue, SIGIO, POLL_IN);
- }
- }
- if (j->port == PORT_PSTN && j->daa_mode == SOP_PU_CONVERSATION)
- fOffHook |= 2;
- if (j->port == PORT_SPEAKER)
- fOffHook |= 2;
- if (j->port == PORT_HANDSET)
- fOffHook |= 2;
- return fOffHook;
- }
- static void ixj_ring_off(board)
- {
- IXJ *j = &ixj[board];
- if (j->dsp.low == 0x20) // Internet PhoneJACK
- {
- if (ixjdebug > 0)
- printk(KERN_INFO "IXJ Ring Offn");
- j->gpio.bytes.high = 0x0B;
- j->gpio.bytes.low = 0x00;
- j->gpio.bits.gpio1 = 0;
- j->gpio.bits.gpio2 = 1;
- j->gpio.bits.gpio5 = 0;
- ixj_WriteDSPCommand(j->gpio.word, board);
- } else // Internet LineJACK
- {
- if (ixjdebug > 0)
- printk(KERN_INFO "IXJ Ring Offn");
- SLIC_SetState(PLD_SLIC_STATE_STANDBY, board);
- SLIC_GetState(board);
- }
- }
- static void ixj_ring_start(int board)
- {
- IXJ *j = &ixj[board];
- j->flags.cringing = 1;
- if (ixj_hookstate(board) & 1) {
- if (j->port == PORT_POTS)
- ixj_ring_off(board);
- j->flags.cringing = 0;
- } else {
- j->ring_cadence_jif = jiffies;
- j->ring_cadence_t = 15;
- if (j->ring_cadence & 1 << j->ring_cadence_t) {
- ixj_ring_on(board);
- } else {
- ixj_ring_off(board);
- }
- }
- }
- static int ixj_ring(int board)
- {
- char cntr;
- unsigned long jif, det;
- IXJ *j = &ixj[board];
- j->flags.ringing = 1;
- if (ixj_hookstate(board) & 1) {
- ixj_ring_off(board);
- j->flags.ringing = 0;
- return 1;
- }
- det = 0;
- for (cntr = 0; cntr < j->maxrings; cntr++) {
- jif = jiffies + (1 * hertz);
- ixj_ring_on(board);
- while (time_before(jiffies, jif)) {
- if (ixj_hookstate(board) & 1) {
- ixj_ring_off(board);
- j->flags.ringing = 0;
- return 1;
- }
- current->state = TASK_INTERRUPTIBLE;
- schedule_timeout(1);
- if (signal_pending(current))
- break;
- }
- jif = jiffies + (3 * hertz);
- ixj_ring_off(board);
- while (time_before(jiffies, jif)) {
- if (ixj_hookstate(board) & 1) {
- det = jiffies + (hertz / 100);
- while (time_before(jiffies, det)) {
- current->state = TASK_INTERRUPTIBLE;
- schedule_timeout(1);
- if (signal_pending(current))
- break;
- }
- if (ixj_hookstate(board) & 1) {
- j->flags.ringing = 0;
- return 1;
- }
- }
- current->state = TASK_INTERRUPTIBLE;
- schedule_timeout(1);
- if (signal_pending(current))
- break;
- }
- }
- ixj_ring_off(board);
- j->flags.ringing = 0;
- return 0;
- }
- int ixj_open(struct phone_device *p, struct file *file_p)
- {
- IXJ *j = &ixj[p->board];
- if (!j->DSPbase)
- return -ENODEV;
- if (file_p->f_mode & FMODE_READ)
- j->readers++;
- if (file_p->f_mode & FMODE_WRITE)
- j->writers++;
- MOD_INC_USE_COUNT;
- if (ixjdebug > 0)
- printk(KERN_INFO "Opening board %dn", p->board);
- return 0;
- }
- int ixj_release(struct inode *inode, struct file *file_p)
- {
- IXJ_TONE ti;
- int board = NUM(inode->i_rdev);
- IXJ *j = &ixj[board];
- if (ixjdebug > 0)
- printk(KERN_INFO "Closing board %dn", NUM(inode->i_rdev));
- daa_set_mode(board, SOP_PU_SLEEP);
- ixj_set_port(board, PORT_POTS);
- aec_stop(board);
- ixj_play_stop(board);
- ixj_record_stop(board);
- // Restore the tone table to default settings.
- ti.tone_index = 10;
- ti.gain0 = 1;
- ti.freq0 = hz941;
- ti.gain1 = 0;
- ti.freq1 = hz1209;
- ti.tone_index = 11;
- ti.gain0 = 1;
- ti.freq0 = hz941;
- ti.gain1 = 0;
- ti.freq1 = hz1336;
- ti.tone_index = 12;
- ti.gain0 = 1;
- ti.freq0 = hz941;
- ti.gain1 = 0;
- ti.freq1 = hz1477;
- ti.tone_index = 13;
- ti.gain0 = 1;
- ti.freq0 = hz800;
- ti.gain1 = 0;
- ti.freq1 = 0;
- ixj_init_tone(board, &ti);
- ti.tone_index = 14;
- ti.gain0 = 1;
- ti.freq0 = hz1000;
- ti.gain1 = 0;
- ti.freq1 = 0;
- ixj_init_tone(board, &ti);
- ti.tone_index = 15;
- ti.gain0 = 1;
- ti.freq0 = hz1250;
- ti.gain1 = 0;
- ti.freq1 = 0;
- ixj_init_tone(board, &ti);
- ti.tone_index = 16;
- ti.gain0 = 1;
- ti.freq0 = hz950;
- ti.gain1 = 0;
- ti.freq1 = 0;
- ixj_init_tone(board, &ti);
- ti.tone_index = 17;
- ti.gain0 = 1;
- ti.freq0 = hz1100;
- ti.gain1 = 0;
- ti.freq1 = 0;
- ixj_init_tone(board, &ti);
- ti.tone_index = 18;
- ti.gain0 = 1;
- ti.freq0 = hz1400;
- ti.gain1 = 0;
- ti.freq1 = 0;
- ixj_init_tone(board, &ti);
- ti.tone_index = 19;
- ti.gain0 = 1;
- ti.freq0 = hz1500;
- ti.gain1 = 0;
- ti.freq1 = 0;
- ixj_init_tone(board, &ti);
- ti.tone_index = 20;
- ti.gain0 = 1;
- ti.freq0 = hz1600;
- ti.gain1 = 0;
- ti.freq1 = 0;
- ixj_init_tone(board, &ti);
- ti.tone_index = 21;
- ti.gain0 = 1;
- ti.freq0 = hz1800;
- ti.gain1 = 0;
- ti.freq1 = 0;
- ixj_init_tone(board, &ti);
- ti.tone_index = 22;
- ti.gain0 = 1;
- ti.freq0 = hz2100;
- ti.gain1 = 0;
- ti.freq1 = 0;
- ixj_init_tone(board, &ti);
- ti.tone_index = 23;
- ti.gain0 = 1;
- ti.freq0 = hz1300;
- ti.gain1 = 0;
- ti.freq1 = 0;
- ixj_init_tone(board, &ti);
- ti.tone_index = 24;
- ti.gain0 = 1;
- ti.freq0 = hz2450;
- ti.gain1 = 0;
- ti.freq1 = 0;
- ixj_init_tone(board, &ti);
- ti.tone_index = 25;
- ti.gain0 = 1;
- ti.freq0 = hz350;
- ti.gain1 = 0;
- ti.freq1 = hz440;
- ixj_init_tone(board, &ti);
- ti.tone_index = 26;
- ti.gain0 = 1;
- ti.freq0 = hz440;
- ti.gain1 = 0;
- ti.freq1 = hz480;
- ixj_init_tone(board, &ti);
- ti.tone_index = 27;
- ti.gain0 = 1;
- ti.freq0 = hz480;
- ti.gain1 = 0;
- ti.freq1 = hz620;
- ixj_init_tone(board, &ti);
- idle(board);
- if (file_p->f_mode & FMODE_READ)
- j->readers--;
- if (file_p->f_mode & FMODE_WRITE)
- j->writers--;
- if (j->read_buffer && !j->readers) {
- kfree(j->read_buffer);
- j->read_buffer = NULL;
- j->read_buffer_size = 0;
- }
- if (j->write_buffer && !j->writers) {
- kfree(j->write_buffer);
- j->write_buffer = NULL;
- j->write_buffer_size = 0;
- }
- j->rec_codec = j->play_codec = 0;
- j->rec_frame_size = j->play_frame_size = 0;
- ixj_fasync(-1, file_p, 0); // remove from list of async notification
- MOD_DEC_USE_COUNT;
- return 0;
- }
- static int read_filters(int board)
- {
- unsigned short fc, cnt;
- int var;
- IXJ *j = &ixj[board];
- if (ixj_WriteDSPCommand(0x5144, board))
- return -1;
- fc = j->ssr.high << 8 | j->ssr.low;
- if (fc == j->frame_count)
- return 1;
- j->frame_count = fc;
- if (j->dtmf_proc)
- return 1;
- var = 10;
- for (cnt = 0; cnt < 4; cnt++) {
- if (ixj_WriteDSPCommand(0x5154 + cnt, board))
- return -1;
- if (ixj_WriteDSPCommand(0x515C, board))
- return -1;
- j->filter_hist[cnt] = j->ssr.high << 8 | j->ssr.low;
- if (j->cadence_f[cnt].enable) {
- if (j->filter_hist[cnt] & 3 && !(j->filter_hist[cnt] & 12)) {
- if (j->cadence_f[cnt].state == 0) {
- j->cadence_f[cnt].state = 1;
- j->cadence_f[cnt].on1min = jiffies + (j->cadence_f[cnt].on1 * hertz * (100 - var) / 10000);
- j->cadence_f[cnt].on1max = jiffies + (j->cadence_f[cnt].on1 * hertz * (100 + var) / 10000);
- } else if (j->cadence_f[cnt].state == 2 &&
- (time_after(jiffies, j->cadence_f[cnt].off1min) &&
- time_before(jiffies, j->cadence_f[cnt].off1max))) {
- if (j->cadence_f[cnt].on2) {
- j->cadence_f[cnt].state = 3;
- j->cadence_f[cnt].on2min = jiffies + (j->cadence_f[cnt].on2 * hertz * (100 - var) / 10000);
- j->cadence_f[cnt].on2max = jiffies + (j->cadence_f[cnt].on2 * hertz * (100 + var) / 10000);
- } else {
- j->cadence_f[cnt].state = 6;
- }
- } else if (j->cadence_f[cnt].state == 4 &&
- (time_after(jiffies, j->cadence_f[cnt].off2min) &&
- time_before(jiffies, j->cadence_f[cnt].off2max))) {
- if (j->cadence_f[cnt].on2) {
- j->cadence_f[cnt].state = 5;
- j->cadence_f[cnt].on3min = jiffies + (j->cadence_f[cnt].on3 * hertz * (100 - var) / 10000);
- j->cadence_f[cnt].on3max = jiffies + (j->cadence_f[cnt].on3 * hertz * (100 + var) / 10000);
- } else {
- j->cadence_f[cnt].state = 6;
- }
- } else {
- j->cadence_f[cnt].state = 0;
- }
- } else if (j->filter_hist[cnt] & 12 && !(j->filter_hist[cnt] & 3)) {
- if (j->cadence_f[cnt].state == 1 &&
- (time_after(jiffies, j->cadence_f[cnt].on1min) &&
- time_before(jiffies, j->cadence_f[cnt].on1max))) {
- j->cadence_f[cnt].state = 2;
- j->cadence_f[cnt].off1min = jiffies + (j->cadence_f[cnt].off1 * hertz * (100 - var) / 10000);
- j->cadence_f[cnt].off1max = jiffies + (j->cadence_f[cnt].off1 * hertz * (100 + var) / 10000);
- } else if (j->cadence_f[cnt].state == 3 &&
- (time_after(jiffies, j->cadence_f[cnt].on2min) &&
- time_before(jiffies, j->cadence_f[cnt].on2max))) {
- j->cadence_f[cnt].state = 4;
- j->cadence_f[cnt].off2min = jiffies + (j->cadence_f[cnt].off2 * hertz * (100 - var) / 10000);
- j->cadence_f[cnt].off2max = jiffies + (j->cadence_f[cnt].off2 * hertz * (100 + var) / 10000);
- } else if (j->cadence_f[cnt].state == 5 &&
- (time_after(jiffies, j->cadence_f[cnt].on3min) &&
- time_before(jiffies, j->cadence_f[cnt].on3max))) {
- j->cadence_f[cnt].state = 6;
- j->cadence_f[cnt].off3min = jiffies + (j->cadence_f[cnt].off3 * hertz * (100 - var) / 10000);
- j->cadence_f[cnt].off3max = jiffies + (j->cadence_f[cnt].off3 * hertz * (100 + var) / 10000);
- } else {
- j->cadence_f[cnt].state = 0;
- }
- }
- }
- if (j->cadence_f[cnt].state == 6) {
- j->cadence_f[cnt].state = j->cadence_f[cnt].enable = 0;
- switch (cnt) {
- case 0:
- j->ex.bits.fc0 = 1;
- break;
- case 1:
- j->ex.bits.fc1 = 1;
- break;
- case 2:
- j->ex.bits.fc2 = 1;
- break;
- case 3:
- j->ex.bits.fc3 = 1;
- break;
- }
- }
- if ((j->filter_hist[cnt] & 3 && !(j->filter_hist[cnt] & 12)) ||
- (j->filter_hist[cnt] & 12 && !(j->filter_hist[cnt] & 3))) {
- switch (cnt) {
- case 0:
- j->ex.bits.f0 = 1;
- break;
- case 1:
- j->ex.bits.f1 = 1;
- break;
- case 2:
- j->ex.bits.f2 = 1;
- break;
- case 3:
- j->ex.bits.f3 = 1;
- break;
- }
- }
- }
- return 0;
- }
- static int LineMonitor(int board)
- {
- IXJ *j = &ixj[board];
- if (j->dtmf_proc) {
- return -1;
- }
- j->dtmf_proc = 1;
- if (ixj_WriteDSPCommand(0x7000, board)) // Line Monitor
- return -1;
- j->dtmf.bytes.high = j->ssr.high;
- j->dtmf.bytes.low = j->ssr.low;
- if (!j->dtmf_state && j->dtmf.bits.dtmf_valid) {
- j->dtmf_state = 1;
- j->dtmf_current = j->dtmf.bits.digit;
- }
- if (j->dtmf_state && !j->dtmf.bits.dtmf_valid) // && j->dtmf_wp != j->dtmf_rp)
- {
- j->dtmfbuffer[j->dtmf_wp] = j->dtmf_current;
- j->dtmf_wp++;
- if (j->dtmf_wp == 79)
- j->dtmf_wp = 0;
- j->ex.bits.dtmf_ready = 1;
- j->dtmf_state = 0;
- }
- j->dtmf_proc = 0;
- return 0;
- }
- ssize_t ixj_read(struct file * file_p, char *buf, size_t length, loff_t * ppos)
- {
- unsigned long i = *ppos;
- IXJ *j = &ixj[NUM(file_p->f_dentry->d_inode->i_rdev)];
- struct wait_queue wait =
- {current, NULL};
- if(j->flags.inread)
- return -EALREADY;
- j->flags.inread = 1;
- add_wait_queue(&j->read_q, &wait);
- current->state = TASK_INTERRUPTIBLE;
- mb();
- while (!j->read_buffer_ready || (j->dtmf_state && j->flags.dtmf_oob)) {
- ++j->read_wait;
- if (file_p->f_flags & O_NONBLOCK) {
- current->state = TASK_RUNNING;
- remove_wait_queue(&j->read_q, &wait);
- j->flags.inread = 0;
- return -EAGAIN;
- }
- if (!ixj_hookstate(NUM(file_p->f_dentry->d_inode->i_rdev))) {
- current->state = TASK_RUNNING;
- remove_wait_queue(&j->read_q, &wait);
- j->flags.inread = 0;
- return 0;
- }
- interruptible_sleep_on(&j->read_q);
- if (signal_pending(current)) {
- current->state = TASK_RUNNING;
- remove_wait_queue(&j->read_q, &wait);
- j->flags.inread = 0;
- return -EINTR;
- }
- }
- remove_wait_queue(&j->read_q, &wait);
- current->state = TASK_RUNNING;
- /* Don't ever copy more than the user asks */
- i = copy_to_user(buf, j->read_buffer, min(length, j->read_buffer_size));
- j->read_buffer_ready = 0;
- if (i) {
- j->flags.inread = 0;
- return -EFAULT;
- }
- else {
- j->flags.inread = 0;
- return min(length, j->read_buffer_size);
- }
- }
- ssize_t ixj_enhanced_read(struct file * file_p, char *buf, size_t length,
- loff_t * ppos)
- {
- int pre_retval;
- ssize_t read_retval = 0;
- IXJ *j = &ixj[NUM(file_p->f_dentry->d_inode->i_rdev)];
- pre_retval = ixj_PreRead(j, 0L);
- switch (pre_retval) {
- case NORMAL:
- read_retval = ixj_read(file_p, buf, length, ppos);
- ixj_PostRead(j, 0L);
- break;
- case NOPOST:
- read_retval = ixj_read(file_p, buf, length, ppos);
- break;
- case POSTONLY:
- ixj_PostRead(j, 0L);
- break;
- default:
- read_retval = pre_retval;
- }
- return read_retval;
- }
- ssize_t ixj_write(struct file * file_p, const char *buf, size_t count, loff_t * ppos)
- {
- unsigned long i = *ppos;
- int board = NUM(file_p->f_dentry->d_inode->i_rdev);
- IXJ *j = &ixj[board];
- struct wait_queue wait =
- {current, NULL};
- if(j->flags.inwrite)
- return -EALREADY;
- j->flags.inwrite = 1;
- add_wait_queue(&j->write_q, &wait);
- current->state = TASK_INTERRUPTIBLE;
- mb();
- while (!j->write_buffers_empty) {
- ++j->write_wait;
- if (file_p->f_flags & O_NONBLOCK) {
- current->state = TASK_RUNNING;
- remove_wait_queue(&j->write_q, &wait);
- j->flags.inwrite = 0;
- return -EAGAIN;
- }
- if (!ixj_hookstate(NUM(file_p->f_dentry->d_inode->i_rdev))) {
- current->state = TASK_RUNNING;
- remove_wait_queue(&j->write_q, &wait);
- j->flags.inwrite = 0;
- return 0;
- }
- interruptible_sleep_on(&j->write_q);
- if (signal_pending(current)) {
- current->state = TASK_RUNNING;
- remove_wait_queue(&j->write_q, &wait);
- j->flags.inwrite = 0;
- return -EINTR;
- }
- }
- current->state = TASK_RUNNING;
- remove_wait_queue(&j->write_q, &wait);
- if (j->write_buffer_wp + count >= j->write_buffer_end)
- j->write_buffer_wp = j->write_buffer;
- i = copy_from_user(j->write_buffer_wp, buf, min(count, j->write_buffer_size));
- if (i) {
- j->flags.inwrite = 0;
- return -EFAULT;
- }
- j->flags.inwrite = 0;
- return min(count, j->write_buffer_size);
- }
- ssize_t ixj_enhanced_write(struct file * file_p, const char *buf, size_t count,
- loff_t * ppos)
- {
- int pre_retval;
- ssize_t write_retval = 0;
- IXJ *j = &ixj[NUM(file_p->f_dentry->d_inode->i_rdev)];
- pre_retval = ixj_PreWrite(j, 0L);
- switch (pre_retval) {
- case NORMAL:
- write_retval = ixj_write(file_p, buf, count, ppos);
- if (write_retval != -EFAULT) {
- ixj_PostWrite(j, 0L);
- j->write_buffer_wp += count;
- j->write_buffers_empty--;
- }
- break;
- case NOPOST:
- write_retval = ixj_write(file_p, buf, count, ppos);
- if (write_retval != -EFAULT) {
- j->write_buffer_wp += count;
- j->write_buffers_empty--;
- }
- break;
- case POSTONLY:
- ixj_PostWrite(j, 0L);
- break;
- default:
- write_retval = pre_retval;
- }
- return write_retval;
- }
- static void ixj_read_frame(int board)
- {
- int cnt, dly;
- IXJ *j = &ixj[board];
- if (j->read_buffer) {
- for (cnt = 0; cnt < j->rec_frame_size * 2; cnt += 2) {
- if (!(cnt % 16) && !IsRxReady(board)) {
- dly = 0;
- while (!IsRxReady(board)) {
- if (dly++ > 5) {
- dly = 0;
- break;
- }
- udelay(10);
- }
- }
- // Throw away word 0 of the 8021 compressed format to get standard G.729.
- if (j->rec_codec == G729 && (cnt == 0 || cnt == 5 || cnt == 10)) {
- inb_p(j->DSPbase + 0x0E);
- inb_p(j->DSPbase + 0x0F);
- }
- *(j->read_buffer + cnt) = inb_p(j->DSPbase + 0x0E);
- *(j->read_buffer + cnt + 1) = inb_p(j->DSPbase + 0x0F);
- }
- #ifdef PERFMON_STATS
- ++j->framesread;
- #endif
- if (j->intercom != -1) {
- if (IsTxReady(j->intercom)) {
- for (cnt = 0; cnt < j->rec_frame_size * 2; cnt += 2) {
- if (!(cnt % 16) && !IsTxReady(board)) {
- dly = 0;
- while (!IsTxReady(board)) {
- if (dly++ > 5) {
- dly = 0;
- break;
- }
- udelay(10);
- }
- }
- outb_p(*(j->read_buffer + cnt), ixj[j->intercom].DSPbase + 0x0C);
- outb_p(*(j->read_buffer + cnt + 1), ixj[j->intercom].DSPbase + 0x0D);
- }
- #ifdef PERFMON_STATS
- ++ixj[j->intercom].frameswritten;
- #endif
- }
- } else {
- j->read_buffer_ready = 1;
- wake_up_interruptible(&j->read_q); // Wake any blocked readers
- wake_up_interruptible(&j->poll_q); // Wake any blocked selects
- if (j->async_queue)
- kill_fasync(ixj[board].async_queue, SIGIO, POLL_IN);
- }
- }
- }
- static void ixj_write_frame(int board)
- {
- int cnt, frame_count, dly;
- BYTES blankword;
- IXJ *j = &ixj[board];
- frame_count = 0;
- if (j->write_buffer && j->write_buffers_empty < 2) {
- if (j->write_buffer_wp > j->write_buffer_rp) {
- frame_count =
- (j->write_buffer_wp - j->write_buffer_rp) / (j->play_frame_size * 2);
- }
- if (j->write_buffer_rp > j->write_buffer_wp) {
- frame_count =
- (j->write_buffer_wp - j->write_buffer) / (j->play_frame_size * 2) +
- (j->write_buffer_end - j->write_buffer_rp) / (j->play_frame_size * 2);
- }
- if (frame_count >= 1) {
- if (j->ver.low == 0x12 && j->play_mode && j->flags.play_first_frame) {
- switch (j->play_mode) {
- case PLAYBACK_MODE_ULAW:
- case PLAYBACK_MODE_ALAW:
- blankword.low = blankword.high = 0xFF;
- break;
- case PLAYBACK_MODE_8LINEAR:
- case PLAYBACK_MODE_16LINEAR:
- blankword.low = blankword.high = 0x00;
- break;
- case PLAYBACK_MODE_8LINEAR_WSS:
- blankword.low = blankword.high = 0x80;
- break;
- }
- for (cnt = 0; cnt < 16; cnt++) {
- if (!(cnt % 16) && !IsTxReady(board)) {
- dly = 0;
- while (!IsTxReady(board)) {
- if (dly++ > 5) {
- dly = 0;
- break;
- }
- udelay(10);
- }
- }
- outb_p((blankword.low), j->DSPbase + 0x0C);
- outb_p((blankword.high), j->DSPbase + 0x0D);
- }
- j->flags.play_first_frame = 0;
- }
- for (cnt = 0; cnt < j->play_frame_size * 2; cnt += 2) {
- if (!(cnt % 16) && !IsTxReady(board)) {
- dly = 0;
- while (!IsTxReady(board)) {
- if (dly++ > 5) {
- dly = 0;
- break;
- }
- udelay(10);
- }
- }
- // Add word 0 to G.729 frames for the 8021. Right now we don't do VAD/CNG
- // so all frames are type 1.
- if (j->play_codec == G729 && (cnt == 0 || cnt == 5 || cnt == 10)) {
- outb_p(0x01, j->DSPbase + 0x0C);
- outb_p(0x00, j->DSPbase + 0x0D);
- }
- outb_p(*(j->write_buffer_rp + cnt), j->DSPbase + 0x0C);
- outb_p(*(j->write_buffer_rp + cnt + 1), j->DSPbase + 0x0D);
- *(j->write_buffer_rp + cnt) = 0;
- *(j->write_buffer_rp + cnt + 1) = 0;
- }
- j->write_buffer_rp += j->play_frame_size * 2;
- if (j->write_buffer_rp >= j->write_buffer_end) {
- j->write_buffer_rp = j->write_buffer;
- }
- j->write_buffers_empty++;
- wake_up_interruptible(&j->write_q); // Wake any blocked writers
- wake_up_interruptible(&j->poll_q); // Wake any blocked selects
- if (j->async_queue)
- kill_fasync(ixj[board].async_queue, SIGIO, POLL_IN);
- #ifdef PERFMON_STATS
- ++j->frameswritten;
- #endif
- }
- } else {
- j->drybuffer++;
- }
- }
- static int idle(int board)
- {
- IXJ *j = &ixj[board];
- if (ixj_WriteDSPCommand(0x0000, board)) // DSP Idle
- return 0;
- if (j->ssr.high || j->ssr.low)
- return 0;
- else
- return 1;
- }
- static int set_base_frame(int board, int size)
- {
- unsigned short cmd;
- int cnt;
- IXJ *j = &ixj[board];
- aec_stop(board);
- for (cnt = 0; cnt < 10; cnt++) {
- if (idle(board))
- break;
- }
- if (j->ssr.high || j->ssr.low)
- return -1;
- if (j->dsp.low != 0x20) {
- switch (size) {
- case 30:
- cmd = 0x07F0;
- /* Set Base Frame Size to 240 pg9-10 8021 */
- break;
- case 20:
- cmd = 0x07A0;
- /* Set Base Frame Size to 160 pg9-10 8021 */
- break;
- case 10:
- cmd = 0x0750;
- /* Set Base Frame Size to 80 pg9-10 8021 */
- break;
- default:
- return -1;
- }
- } else {
- if (size == 30)
- return size;
- else
- return -1;
- }
- if (ixj_WriteDSPCommand(cmd, board)) {
- j->baseframe.high = j->baseframe.low = 0xFF;
- return -1;
- } else {
- j->baseframe.high = j->ssr.high;
- j->baseframe.low = j->ssr.low;
- }
- return size;
- }
- static int set_rec_codec(int board, int rate)
- {
- int retval = 0;
- IXJ *j = &ixj[board];
- j->rec_codec = rate;
- switch (rate) {
- case G723_63:
- if (j->ver.low != 0x12 || ixj_convert_loaded) {
- j->rec_frame_size = 12;
- j->rec_mode = 0;
- } else {
- retval = 1;
- }
- break;
- case G723_53:
- if (j->ver.low != 0x12 || ixj_convert_loaded) {
- j->rec_frame_size = 10;
- j->rec_mode = 0;
- } else {
- retval = 1;
- }
- break;
- case TS85:
- if (j->dsp.low == 0x20 || j->flags.ts85_loaded) {
- j->rec_frame_size = 16;
- j->rec_mode = 0;
- } else {
- retval = 1;
- }
- break;
- case TS48:
- if (j->ver.low != 0x12 || ixj_convert_loaded) {
- j->rec_frame_size = 9;
- j->rec_mode = 0;
- } else {
- retval = 1;
- }
- break;
- case TS41:
- if (j->ver.low != 0x12 || ixj_convert_loaded) {
- j->rec_frame_size = 8;
- j->rec_mode = 0;
- } else {
- retval = 1;
- }
- break;
- case G728:
- if (j->dsp.low != 0x20) {
- j->rec_frame_size = 48;
- j->rec_mode = 0;
- } else {
- retval = 1;
- }
- break;
- case G729:
- if (j->dsp.low != 0x20) {
- if (!j->flags.g729_loaded) {
- retval = 1;
- break;
- }
- switch (j->baseframe.low) {
- case 0xA0:
- j->rec_frame_size = 10;
- break;
- case 0x50:
- j->rec_frame_size = 5;
- break;
- default:
- j->rec_frame_size = 15;
- break;
- }
- j->rec_mode = 0;
- } else {
- retval = 1;
- }
- break;
- case ULAW:
- switch (j->baseframe.low) {
- case 0xA0:
- j->rec_frame_size = 80;
- break;
- case 0x50:
- j->rec_frame_size = 40;
- break;
- default:
- j->rec_frame_size = 120;
- break;
- }
- j->rec_mode = 4;
- break;
- case ALAW:
- switch (j->baseframe.low) {
- case 0xA0:
- j->rec_frame_size = 80;
- break;
- case 0x50:
- j->rec_frame_size = 40;
- break;
- default:
- j->rec_frame_size = 120;
- break;
- }
- j->rec_mode = 4;
- break;
- case LINEAR16:
- switch (j->baseframe.low) {
- case 0xA0:
- j->rec_frame_size = 160;
- break;
- case 0x50:
- j->rec_frame_size = 80;
- break;
- default:
- j->rec_frame_size = 240;
- break;
- }
- j->rec_mode = 5;
- break;
- case LINEAR8:
- switch (j->baseframe.low) {
- case 0xA0:
- j->rec_frame_size = 80;
- break;
- case 0x50:
- j->rec_frame_size = 40;
- break;
- default:
- j->rec_frame_size = 120;
- break;
- }
- j->rec_mode = 6;
- break;
- case WSS:
- switch (j->baseframe.low) {
- case 0xA0:
- j->rec_frame_size = 80;
- break;
- case 0x50:
- j->rec_frame_size = 40;
- break;
- default:
- j->rec_frame_size = 120;
- break;
- }
- j->rec_mode = 7;
- break;
- default:
- j->rec_frame_size = 0;
- j->rec_mode = -1;
- if (j->read_buffer) {
- kfree(j->read_buffer);
- j->read_buffer = NULL;
- j->read_buffer_size = 0;
- }
- retval = 1;
- break;
- }
- return retval;
- }
- static int ixj_record_start(int board)
- {
- unsigned short cmd = 0x0000;
- IXJ *j = &ixj[board];
- if (j->read_buffer) {
- ixj_record_stop(board);
- }
- if (!j->rec_mode) {
- switch (j->rec_codec) {
- case G723_63:
- cmd = 0x5131;
- break;
- case G723_53:
- cmd = 0x5132;
- break;
- case TS85:
- cmd = 0x5130; // TrueSpeech 8.5
- break;
- case TS48:
- cmd = 0x5133; // TrueSpeech 4.8
- break;
- case TS41:
- cmd = 0x5134; // TrueSpeech 4.1
- break;
- case G728:
- cmd = 0x5135;
- break;
- case G729:
- cmd = 0x5136;
- break;
- default:
- return 1;
- }
- if (ixj_WriteDSPCommand(cmd, board))
- return -1;
- }
- if (!j->read_buffer) {
- if (!j->read_buffer)
- j->read_buffer = kmalloc(j->rec_frame_size * 2, GFP_ATOMIC);
- if (!j->read_buffer) {
- printk("Read buffer allocation for ixj board %d failed!n", board);
- return -ENOMEM;
- }
- }
- j->read_buffer_size = j->rec_frame_size * 2;
- if (ixj_WriteDSPCommand(0x5102, board)) // Set Poll sync mode
- return -1;
- switch (j->rec_mode) {
- case 0:
- cmd = 0x1C03; // Record C1
- break;
- case 4:
- if (j->ver.low == 0x12) {
- cmd = 0x1E03; // Record C1
- } else {
- cmd = 0x1E01; // Record C1
- }
- break;
- case 5:
- if (j->ver.low == 0x12) {
- cmd = 0x1E83; // Record C1
- } else {
- cmd = 0x1E81; // Record C1
- }
- break;
- case 6:
- if (j->ver.low == 0x12) {
- cmd = 0x1F03; // Record C1
- } else {
- cmd = 0x1F01; // Record C1
- }
- break;
- case 7:
- if (j->ver.low == 0x12) {
- cmd = 0x1F83; // Record C1
- } else {
- cmd = 0x1F81; // Record C1
- }
- break;
- }
- if (ixj_WriteDSPCommand(cmd, board))
- return -1;
- return 0;
- }
- static void ixj_record_stop(int board)
- {
- IXJ *j = &ixj[board];
- if (j->read_buffer) {
- kfree(j->read_buffer);
- j->read_buffer = NULL;
- j->read_buffer_size = 0;
- }
- if (j->rec_mode > -1) {
- ixj_WriteDSPCommand(0x5120, board);
- j->rec_mode = -1;
- }
- }
- static void ixj_vad(int board, int arg)
- {
- if (arg)
- ixj_WriteDSPCommand(0x513F, board);
- else
- ixj_WriteDSPCommand(0x513E, board);
- }
- static void set_rec_depth(int board, int depth)
- {
- if (depth > 60)
- depth = 60;
- if (depth < 0)
- depth = 0;
- ixj_WriteDSPCommand(0x5180 + depth, board);
- }
- static void set_rec_volume(int board, int volume)
- {
- ixj_WriteDSPCommand(0xCF03, board);
- ixj_WriteDSPCommand(volume, board);
- }
- static int get_rec_level(int board)
- {
- IXJ *j = &ixj[board];
- ixj_WriteDSPCommand(0xCF88, board);
- return j->ssr.high << 8 | j->ssr.low;
- }
- static void ixj_aec_start(int board, int level)
- {
- IXJ *j = &ixj[board];
- j->aec_level = level;
- if (!level) {
- ixj_WriteDSPCommand(0xB002, board);
- } else {
- if (j->rec_codec == G729 || j->play_codec == G729) {
- ixj_WriteDSPCommand(0xE022, board); // Move AEC filter buffer
- ixj_WriteDSPCommand(0x0300, board);
- }
- ixj_WriteDSPCommand(0xB001, board); // AEC On
- ixj_WriteDSPCommand(0xE013, board); // Advanced AEC C1
- switch (level) {
- case AEC_LOW:
- ixj_WriteDSPCommand(0x0000, board); // Advanced AEC C2 = off
- ixj_WriteDSPCommand(0xE011, board);
- ixj_WriteDSPCommand(0xFFFF, board);
- break;
- case AEC_MED:
- ixj_WriteDSPCommand(0x0600, board); // Advanced AEC C2 = on medium
- ixj_WriteDSPCommand(0xE011, board);
- ixj_WriteDSPCommand(0x0080, board);
- break;
- case AEC_HIGH:
- ixj_WriteDSPCommand(0x0C00, board); // Advanced AEC C2 = on high
- ixj_WriteDSPCommand(0xE011, board);
- ixj_WriteDSPCommand(0x0080, board);
- break;
- case AEC_AUTO:
- ixj_WriteDSPCommand(0x0002, board); // Attenuation scaling factor of 2
- ixj_WriteDSPCommand(0xE011, board);
- ixj_WriteDSPCommand(0x0100, board); // Higher Threshold Floor
- ixj_WriteDSPCommand(0xE012, board); // Set Train and Lock
- ixj_WriteDSPCommand(0x0023, board);
- ixj_WriteDSPCommand(0xE014, board);
- ixj_WriteDSPCommand(0x0003, board); // Lock threashold at 3dB
- break;
- }
- }
- }
- static void aec_stop(int board)
- {
- IXJ *j = &ixj[board];
- if (j->rec_codec == G729 || j->play_codec == G729) {
- ixj_WriteDSPCommand(0xE022, board); // Move AEC filter buffer back
- ixj_WriteDSPCommand(0x0700, board);
- }
- if (ixj[board].play_mode != -1 && ixj[board].rec_mode != -1);
- {
- ixj_WriteDSPCommand(0xB002, board); // AEC Stop
- }
- }
- static int set_play_codec(int board, int rate)
- {
- int retval = 0;
- IXJ *j = &ixj[board];
- j->play_codec = rate;
- switch (rate) {
- case G723_63:
- if (j->ver.low != 0x12 || ixj_convert_loaded) {
- j->play_frame_size = 12;
- j->play_mode = 0;
- } else {
- retval = 1;
- }
- break;
- case G723_53:
- if (j->ver.low != 0x12 || ixj_convert_loaded) {
- j->play_frame_size = 10;
- j->play_mode = 0;
- } else {
- retval = 1;
- }
- break;
- case TS85:
- if (j->dsp.low == 0x20 || j->flags.ts85_loaded) {
- j->play_frame_size = 16;
- j->play_mode = 0;
- } else {
- retval = 1;
- }
- break;
- case TS48:
- if (j->ver.low != 0x12 || ixj_convert_loaded) {
- j->play_frame_size = 9;
- j->play_mode = 0;
- } else {
- retval = 1;
- }
- break;
- case TS41:
- if (j->ver.low != 0x12 || ixj_convert_loaded) {
- j->play_frame_size = 8;
- j->play_mode = 0;
- } else {
- retval = 1;
- }
- break;
- case G728:
- if (j->dsp.low != 0x20) {
- j->play_frame_size = 48;
- j->play_mode = 0;
- } else {
- retval = 1;
- }
- break;
- case G729:
- if (j->dsp.low != 0x20) {
- if (!j->flags.g729_loaded) {
- retval = 1;
- break;
- }
- switch (j->baseframe.low) {
- case 0xA0:
- j->play_frame_size = 10;
- break;
- case 0x50:
- j->play_frame_size = 5;
- break;
- default:
- j->play_frame_size = 15;
- break;
- }
- j->play_mode = 0;
- } else {
- retval = 1;
- }
- break;
- case ULAW:
- switch (j->baseframe.low) {
- case 0xA0:
- j->play_frame_size = 80;
- break;
- case 0x50:
- j->play_frame_size = 40;
- break;
- default:
- j->play_frame_size = 120;
- break;
- }
- j->play_mode = 2;
- break;
- case ALAW:
- switch (j->baseframe.low) {
- case 0xA0:
- j->play_frame_size = 80;
- break;
- case 0x50:
- j->play_frame_size = 40;
- break;
- default:
- j->play_frame_size = 120;
- break;
- }
- j->play_mode = 2;
- break;
- case LINEAR16:
- switch (j->baseframe.low) {
- case 0xA0:
- j->play_frame_size = 160;
- break;
- case 0x50:
- j->play_frame_size = 80;
- break;
- default:
- j->play_frame_size = 240;
- break;
- }
- j->play_mode = 6;
- break;
- case LINEAR8:
- switch (j->baseframe.low) {
- case 0xA0:
- j->play_frame_size = 80;
- break;
- case 0x50:
- j->play_frame_size = 40;
- break;
- default:
- j->play_frame_size = 120;
- break;
- }
- j->play_mode = 4;
- break;
- case WSS:
- switch (j->baseframe.low) {
- case 0xA0:
- j->play_frame_size = 80;
- break;
- case 0x50:
- j->play_frame_size = 40;
- break;
- default:
- j->play_frame_size = 120;
- break;
- }
- j->play_mode = 5;
- break;
- default:
- j->play_frame_size = 0;
- j->play_mode = -1;
- if (j->write_buffer) {
- kfree(j->write_buffer);
- j->write_buffer = NULL;
- j->write_buffer_size = 0;
- }
- retval = 1;
- break;
- }
- return retval;
- }
- static int ixj_play_start(int board)
- {
- unsigned short cmd = 0x0000;
- IXJ *j = &ixj[board];
- if (j->write_buffer) {
- ixj_play_stop(board);
- }
- j->flags.play_first_frame = 1;
- j->drybuffer = 0;
- if (!j->play_mode) {
- switch (j->play_codec) {
- case G723_63:
- cmd = 0x5231;
- break;
- case G723_53:
- cmd = 0x5232;
- break;
- case TS85:
- cmd = 0x5230; // TrueSpeech 8.5
- break;
- case TS48:
- cmd = 0x5233; // TrueSpeech 4.8
- break;
- case TS41:
- cmd = 0x5234; // TrueSpeech 4.1
- break;
- case G728:
- cmd = 0x5235;
- break;
- case G729:
- cmd = 0x5236;
- break;
- default:
- return 1;
- }
- if (ixj_WriteDSPCommand(cmd, board))
- return -1;
- }
- j->write_buffer = kmalloc(j->play_frame_size * 2, GFP_ATOMIC);
- if (!j->write_buffer) {
- printk("Write buffer allocation for ixj board %d failed!n", board);
- return -ENOMEM;
- }
- j->write_buffers_empty = 2;
- j->write_buffer_size = j->play_frame_size * 2;
- j->write_buffer_end = j->write_buffer + j->play_frame_size * 2;
- j->write_buffer_rp = j->write_buffer_wp = j->write_buffer;
- if (ixj_WriteDSPCommand(0x5202, board)) // Set Poll sync mode
- return -1;
- switch (j->play_mode) {
- case 0:
- cmd = 0x2C03;
- break;
- case 2:
- if (j->ver.low == 0x12) {
- cmd = 0x2C23;
- } else {
- cmd = 0x2C21;
- }
- break;
- case 4:
- if (j->ver.low == 0x12) {
- cmd = 0x2C43;
- } else {
- cmd = 0x2C41;
- }
- break;
- case 5:
- if (j->ver.low == 0x12) {
- cmd = 0x2C53;
- } else {
- cmd = 0x2C51;
- }
- break;
- case 6:
- if (j->ver.low == 0x12) {
- cmd = 0x2C63;
- } else {
- cmd = 0x2C61;
- }
- break;
- }
- if (ixj_WriteDSPCommand(cmd, board))
- return -1;
- if (ixj_WriteDSPCommand(0x2000, board)) // Playback C2
- return -1;
- if (ixj_WriteDSPCommand(0x2000 + ixj[board].play_frame_size, board)) // Playback C3
- return -1;
- return 0;
- }
- static void ixj_play_stop(int board)
- {
- IXJ *j = &ixj[board];
- if (j->write_buffer) {
- kfree(j->write_buffer);
- j->write_buffer = NULL;
- j->write_buffer_size = 0;
- }
- if (j->play_mode > -1) {
- ixj_WriteDSPCommand(0x5221, board); // Stop playback
- j->play_mode = -1;
- }
- }
- extern __inline__ void set_play_depth(int board, int depth)
- {
- if (depth > 60)
- depth = 60;
- if (depth < 0)
- depth = 0;
- ixj_WriteDSPCommand(0x5280 + depth, board);
- }
- extern __inline__ void set_play_volume(int board, int volume)
- {
- ixj_WriteDSPCommand(0xCF02, board);
- ixj_WriteDSPCommand(volume, board);
- }
- extern __inline__ int get_play_level(int board)
- {
- ixj_WriteDSPCommand(0xCF8F, board);
- return ixj[board].ssr.high << 8 | ixj[board].ssr.low;
- }
- static unsigned int ixj_poll(struct file *file_p, poll_table * wait)
- {
- unsigned int mask = 0;
- IXJ *j = &ixj[NUM(file_p->f_dentry->d_inode->i_rdev)];
- poll_wait(file_p, &(j->poll_q), wait);
- if (j->read_buffer_ready > 0)
- mask |= POLLIN | POLLRDNORM; /* readable */
- if (j->write_buffers_empty > 0)
- mask |= POLLOUT | POLLWRNORM; /* writable */
- if (j->ex.bytes)
- mask |= POLLPRI;
- return mask;
- }
- static int ixj_play_tone(int board, char tone)
- {
- IXJ *j = &ixj[board];
- if (!j->tone_state)
- idle(board);
- j->tone_index = tone;
- if (ixj_WriteDSPCommand(0x6000 + j->tone_index, board))
- return -1;
- if (!j->tone_state) {
- j->tone_start_jif = jiffies;
- j->tone_state = 1;
- }
- return 0;
- }
- static int ixj_set_tone_on(unsigned short arg, int board)
- {
- IXJ *j = &ixj[board];
- j->tone_on_time = arg;
- if (ixj_WriteDSPCommand(0x6E04, board)) // Set Tone On Period
- return -1;
- if (ixj_WriteDSPCommand(arg, board))
- return -1;
- return 0;
- }
- static int SCI_WaitHighSCI(int board)
- {
- int cnt;
- IXJ *j = &ixj[board];
- j->pld_scrr.byte = inb_p(j->XILINXbase);
- if (!j->pld_scrr.bits.sci) {
- for (cnt = 0; cnt < 10; cnt++) {
- udelay(32);
- j->pld_scrr.byte = inb_p(j->XILINXbase);
- if ((j->pld_scrr.bits.sci))
- return 1;
- }
- if (ixjdebug > 1)
- printk(KERN_INFO "SCI Wait High failed %xn", j->pld_scrr.byte);
- return 0;
- } else
- return 1;
- }
- static int SCI_WaitLowSCI(int board)
- {
- int cnt;
- IXJ *j = &ixj[board];
- j->pld_scrr.byte = inb_p(j->XILINXbase);
- if (j->pld_scrr.bits.sci) {
- for (cnt = 0; cnt < 10; cnt++) {
- udelay(32);
- j->pld_scrr.byte = inb_p(j->XILINXbase);
- if (!(j->pld_scrr.bits.sci))
- return 1;
- }
- if (ixjdebug > 1)
- printk(KERN_INFO "SCI Wait Low failed %xn", j->pld_scrr.byte);
- return 0;
- } else
- return 1;
- }
- static int SCI_Control(int board, int control)
- {
- IXJ *j = &ixj[board];
- switch (control) {
- case SCI_End:
- j->pld_scrw.bits.c0 = 0; // Set PLD Serial control interface
- j->pld_scrw.bits.c1 = 0; // to no selection
- break;
- case SCI_Enable_DAA:
- j->pld_scrw.bits.c0 = 1; // Set PLD Serial control interface
- j->pld_scrw.bits.c1 = 0; // to write to DAA
- break;
- case SCI_Enable_Mixer:
- j->pld_scrw.bits.c0 = 0; // Set PLD Serial control interface
- j->pld_scrw.bits.c1 = 1; // to write to mixer
- break;
- case SCI_Enable_EEPROM:
- j->pld_scrw.bits.c0 = 1; // Set PLD Serial control interface
- j->pld_scrw.bits.c1 = 1; // to write to EEPROM
- break;
- default:
- return 0;
- break;
- }
- outb_p(j->pld_scrw.byte, j->XILINXbase);
- switch (control) {
- case SCI_End:
- return 1;
- break;
- case SCI_Enable_DAA:
- case SCI_Enable_Mixer:
- case SCI_Enable_EEPROM:
- if (!SCI_WaitHighSCI(board))
- return 0;
- break;
- default:
- return 0;
- break;
- }
- return 1;
- }
- static int SCI_Prepare(int board)
- {
- if (!SCI_Control(board, SCI_End))
- return 0;
- if (!SCI_WaitLowSCI(board))
- return 0;
- return 1;
- }
- static int ixj_mixer(long val, int board)
- {
- BYTES bytes;
- IXJ *j = &ixj[board];
- bytes.high = (val & 0xFF00) >> 8;
- bytes.low = val & 0x00FF;
- outb_p(bytes.high & 0x1F, j->XILINXbase + 0x03); // Load Mixer Address
- outb_p(bytes.low, j->XILINXbase + 0x02); // Load Mixer Data
- SCI_Control(board, SCI_Enable_Mixer);
- SCI_Control(board, SCI_End);
- return 0;
- }
- static int daa_load(BYTES * p_bytes, int board)
- {
- IXJ *j = &ixj[board];
- outb_p(p_bytes->high, j->XILINXbase + 0x03);
- outb_p(p_bytes->low, j->XILINXbase + 0x02);
- if (!SCI_Control(board, SCI_Enable_DAA))
- return 0;
- else
- return 1;
- }
- static int ixj_daa_cr4(int board, char reg)
- {
- IXJ *j = &ixj[board];
- BYTES bytes;
- switch (j->daa_mode) {
- case SOP_PU_SLEEP:
- bytes.high = 0x14;
- break;
- case SOP_PU_RINGING:
- bytes.high = 0x54;
- break;
- case SOP_PU_CONVERSATION:
- bytes.high = 0x94;
- break;
- case SOP_PU_PULSEDIALING:
- bytes.high = 0xD4;
- break;
- }
- j->m_DAAShadowRegs.SOP_REGS.SOP.cr4.reg = reg;
- switch (j->m_DAAShadowRegs.SOP_REGS.SOP.cr4.bitreg.AGX) {
- case 0:
- j->m_DAAShadowRegs.SOP_REGS.SOP.cr4.bitreg.AGR_Z = 0;
- break;
- case 1:
- j->m_DAAShadowRegs.SOP_REGS.SOP.cr4.bitreg.AGR_Z = 2;
- break;
- case 2:
- j->m_DAAShadowRegs.SOP_REGS.SOP.cr4.bitreg.AGR_Z = 1;
- break;
- case 3:
- j->m_DAAShadowRegs.SOP_REGS.SOP.cr4.bitreg.AGR_Z = 3;
- break;
- }
- bytes.low = j->m_DAAShadowRegs.SOP_REGS.SOP.cr4.reg;
- if (!daa_load(&bytes, board))
- return 0;
- if (!SCI_Prepare(board))
- return 0;
- return 1;
- }
- static char daa_int_read(int board)
- {
- BYTES bytes;
- IXJ *j = &ixj[board];
- if (!SCI_Prepare(board))
- return 0;
- bytes.high = 0x38;
- bytes.low = 0x00;
- outb_p(bytes.high, j->XILINXbase + 0x03);
- outb_p(bytes.low, j->XILINXbase + 0x02);
- if (!SCI_Control(board, SCI_Enable_DAA))
- return 0;
- bytes.high = inb_p(j->XILINXbase + 0x03);
- bytes.low = inb_p(j->XILINXbase + 0x02);
- if (bytes.low != ALISDAA_ID_BYTE) {
- if (ixjdebug > 0)
- printk("Cannot read DAA ID Byte high = %d low = %dn", bytes.high, bytes.low);
- return 0;
- }
- if (!SCI_Control(board, SCI_Enable_DAA))
- return 0;
- if (!SCI_Control(board, SCI_End))
- return 0;
- bytes.high = inb_p(j->XILINXbase + 0x03);
- bytes.low = inb_p(j->XILINXbase + 0x02);
- j->m_DAAShadowRegs.XOP_REGS.XOP.xr0.reg = bytes.high;
- return 1;
- }
- static int ixj_daa_cid_reset(int board)
- {
- int i;
- BYTES bytes;
- IXJ *j = &ixj[board];
- if (!SCI_Prepare(board))
- return 0;
- bytes.high = 0x58;
- bytes.low = 0x00;
- outb_p(bytes.high, j->XILINXbase + 0x03);
- outb_p(bytes.low, j->XILINXbase + 0x02);
- if (!SCI_Control(board, SCI_Enable_DAA))
- return 0;
- if (!SCI_WaitHighSCI(board))
- return 0;
- for (i = 0; i < ALISDAA_CALLERID_SIZE - 1; i += 2) {
- bytes.high = bytes.low = 0x00;
- outb_p(bytes.high, j->XILINXbase + 0x03);
- if (i < ALISDAA_CALLERID_SIZE - 1)
- outb_p(bytes.low, j->XILINXbase + 0x02);
- if (!SCI_Control(board, SCI_Enable_DAA))
- return 0;
- if (!SCI_WaitHighSCI(board))
- return 0;
- }
- if (!SCI_Control(board, SCI_End))
- return 0;
- return 1;
- }
- static int ixj_daa_cid_read(int board)
- {
- int i;
- BYTES bytes;
- char CID[ALISDAA_CALLERID_SIZE], mContinue;
- char *pIn, *pOut;
- IXJ *j = &ixj[board];
- if (!SCI_Prepare(board))
- return 0;
- bytes.high = 0x78;
- bytes.low = 0x00;
- outb_p(bytes.high, j->XILINXbase + 0x03);
- outb_p(bytes.low, j->XILINXbase + 0x02);
- if (!SCI_Control(board, SCI_Enable_DAA))
- return 0;
- if (!SCI_WaitHighSCI(board))
- return 0;
- bytes.high = inb_p(j->XILINXbase + 0x03);
- bytes.low = inb_p(j->XILINXbase + 0x02);
- if (bytes.low != ALISDAA_ID_BYTE) {
- if (ixjdebug > 0)
- printk("DAA Get Version Cannot read DAA ID Byte high = %d low = %dn", bytes.high, bytes.low);
- return 0;
- }
- for (i = 0; i < ALISDAA_CALLERID_SIZE; i += 2) {
- bytes.high = bytes.low = 0x00;
- outb_p(bytes.high, j->XILINXbase + 0x03);
- outb_p(bytes.low, j->XILINXbase + 0x02);
- if (!SCI_Control(board, SCI_Enable_DAA))
- return 0;
- if (!SCI_WaitHighSCI(board))
- return 0;
- CID[i + 0] = inb_p(j->XILINXbase + 0x03);
- CID[i + 1] = inb_p(j->XILINXbase + 0x02);
- }
- if (!SCI_Control(board, SCI_End))
- return 0;
- pIn = CID;
- pOut = j->m_DAAShadowRegs.CAO_REGS.CAO.CallerID;
- mContinue = 1;
- while (mContinue) {
- if ((pIn[1] & 0x03) == 0x01) {
- pOut[0] = pIn[0];
- }
- if ((pIn[2] & 0x0c) == 0x04) {
- pOut[1] = ((pIn[2] & 0x03) << 6) | ((pIn[1] & 0xfc) >> 2);
- }
- if ((pIn[3] & 0x30) == 0x10) {
- pOut[2] = ((pIn[3] & 0x0f) << 4) | ((pIn[2] & 0xf0) >> 4);
- }
- if ((pIn[4] & 0xc0) == 0x40) {
- pOut[3] = ((pIn[4] & 0x3f) << 2) | ((pIn[3] & 0xc0) >> 6);
- } else {
- mContinue = FALSE;
- }
- pIn += 5, pOut += 4;
- }
- memset(&j->cid, 0, sizeof(IXJ_CID));
- pOut = j->m_DAAShadowRegs.CAO_REGS.CAO.CallerID;
- pOut += 4;
- strncpy(j->cid.month, pOut, 2);
- pOut += 2;
- strncpy(j->cid.day, pOut, 2);
- pOut += 2;
- strncpy(j->cid.hour, pOut, 2);
- pOut += 2;
- strncpy(j->cid.min, pOut, 2);
- pOut += 3;
- j->cid.numlen = *pOut;
- pOut += 1;
- strncpy(j->cid.number, pOut, j->cid.numlen);
- pOut += j->cid.numlen + 1;
- j->cid.namelen = *pOut;
- pOut += 1;
- strncpy(j->cid.name, pOut, j->cid.namelen);
- ixj_daa_cid_reset(board);
- return 1;
- }
- static char daa_get_version(int board)
- {
- BYTES bytes;
- IXJ *j = &ixj[board];
- if (!SCI_Prepare(board))
- return 0;
- bytes.high = 0x35;
- bytes.low = 0x00;
- outb_p(bytes.high, j->XILINXbase + 0x03);
- outb_p(bytes.low, j->XILINXbase + 0x02);
- if (!SCI_Control(board, SCI_Enable_DAA))
- return 0;
- bytes.high = inb_p(j->XILINXbase + 0x03);
- bytes.low = inb_p(j->XILINXbase + 0x02);
- if (bytes.low != ALISDAA_ID_BYTE) {
- if (ixjdebug > 0)
- printk("DAA Get Version Cannot read DAA ID Byte high = %d low = %dn", bytes.high, bytes.low);
- return 0;
- }
- if (!SCI_Control(board, SCI_Enable_DAA))
- return 0;
- if (!SCI_Control(board, SCI_End))
- return 0;
- bytes.high = inb_p(j->XILINXbase + 0x03);
- bytes.low = inb_p(j->XILINXbase + 0x02);
- if (ixjdebug > 0)
- printk("DAA CR5 Byte high = 0x%x low = 0x%xn", bytes.high, bytes.low);
- j->m_DAAShadowRegs.SOP_REGS.SOP.cr5.reg = bytes.high;
- return bytes.high;
- }
- static int daa_set_mode(int board, int mode)
- {
- // NOTE:
- // The DAA *MUST* be in the conversation mode if the
- // PSTN line is to be seized (PSTN line off-hook).
- // Taking the PSTN line off-hook while the DAA is in
- // a mode other than conversation mode will cause a
- // hardware failure of the ALIS-A part.
- // NOTE:
- // The DAA can only go to SLEEP, RINGING or PULSEDIALING modes
- // if the PSTN line is on-hook. Failure to have the PSTN line
- // in the on-hook state WILL CAUSE A HARDWARE FAILURE OF THE
- // ALIS-A part.
- //
- BYTES bytes;
- IXJ *j = &ixj[board];
- if (!SCI_Prepare(board))
- return 0;
- switch (mode) {
- case SOP_PU_SLEEP:
- j->pld_scrw.bits.daafsyncen = 0; // Turn off DAA Frame Sync
- outb_p(j->pld_scrw.byte, j->XILINXbase);
- j->pld_slicw.bits.rly2 = 0;
- outb_p(j->pld_slicw.byte, j->XILINXbase + 0x01);
- bytes.high = 0x10;
- bytes.low = j->m_DAAShadowRegs.SOP_REGS.SOP.cr0.reg;
- daa_load(&bytes, board);
- if (!SCI_Prepare(board))
- return 0;
- j->daa_mode = SOP_PU_SLEEP;
- j->flags.pstn_ringing = 0;
- j->pstn_sleeptil = jiffies + (hertz * 3);
- break;
- case SOP_PU_RINGING:
- j->pld_scrw.bits.daafsyncen = 0; // Turn off DAA Frame Sync
- outb_p(j->pld_scrw.byte, j->XILINXbase);
- j->pld_slicw.bits.rly2 = 0;
- outb_p(j->pld_slicw.byte, j->XILINXbase + 0x01);
- bytes.high = 0x50;
- bytes.low = j->m_DAAShadowRegs.SOP_REGS.SOP.cr0.reg;
- daa_load(&bytes, board);
- if (!SCI_Prepare(board))
- return 0;
- j->daa_mode = SOP_PU_RINGING;
- break;
- case SOP_PU_CONVERSATION:
- bytes.high = 0x90;
- bytes.low = j->m_DAAShadowRegs.SOP_REGS.SOP.cr0.reg;
- daa_load(&bytes, board);
- if (!SCI_Prepare(board))
- return 0;
- j->pld_slicw.bits.rly2 = 1;
- outb_p(j->pld_slicw.byte, j->XILINXbase + 0x01);
- j->pld_scrw.bits.daafsyncen = 1; // Turn on DAA Frame Sync
- outb_p(j->pld_scrw.byte, j->XILINXbase);
- j->daa_mode = SOP_PU_CONVERSATION;
- j->flags.pstn_ringing = 0;
- j->ex.bits.pstn_ring = 0;
- break;
- case SOP_PU_PULSEDIALING:
- j->pld_scrw.bits.daafsyncen = 0; // Turn off DAA Frame Sync
- outb_p(j->pld_scrw.byte, j->XILINXbase);
- j->pld_slicw.bits.rly2 = 0;
- outb_p(j->pld_slicw.byte, j->XILINXbase + 0x01);
- bytes.high = 0xD0;
- bytes.low = j->m_DAAShadowRegs.SOP_REGS.SOP.cr0.reg;
- daa_load(&bytes, board);
- if (!SCI_Prepare(board))
- return 0;
- j->daa_mode = SOP_PU_PULSEDIALING;
- break;
- default:
- break;
- }
- return 1;
- }
- static int ixj_daa_write(int board)
- {
- BYTES bytes;
- IXJ *j = &ixj[board];
- if (!SCI_Prepare(board))
- return 0;
- bytes.high = 0x14;
- bytes.low = j->m_DAAShadowRegs.SOP_REGS.SOP.cr4.reg;
- if (!daa_load(&bytes, board))
- return 0;
- bytes.high = j->m_DAAShadowRegs.SOP_REGS.SOP.cr3.reg;
- bytes.low = j->m_DAAShadowRegs.SOP_REGS.SOP.cr2.reg;
- if (!daa_load(&bytes, board))
- return 0;
- bytes.high = j->m_DAAShadowRegs.SOP_REGS.SOP.cr1.reg;
- bytes.low = j->m_DAAShadowRegs.SOP_REGS.SOP.cr0.reg;
- if (!daa_load(&bytes, board))
- return 0;
- if (!SCI_Prepare(board))
- return 0;
- bytes.high = 0x1F;
- bytes.low = j->m_DAAShadowRegs.XOP_REGS.XOP.xr7.reg;
- if (!daa_load(&bytes, board))
- return 0;
- bytes.high = j->m_DAAShadowRegs.XOP_xr6_W.reg;
- bytes.low = j->m_DAAShadowRegs.XOP_REGS.XOP.xr5.reg;
- if (!daa_load(&bytes, board))
- return 0;
- bytes.high = j->m_DAAShadowRegs.XOP_REGS.XOP.xr4.reg;
- bytes.low = j->m_DAAShadowRegs.XOP_REGS.XOP.xr3.reg;
- if (!daa_load(&bytes, board))
- return 0;
- bytes.high = j->m_DAAShadowRegs.XOP_REGS.XOP.xr2.reg;
- bytes.low = j->m_DAAShadowRegs.XOP_REGS.XOP.xr1.reg;
- if (!daa_load(&bytes, board))
- return 0;
- bytes.high = j->m_DAAShadowRegs.XOP_xr0_W.reg;
- bytes.low = 0x00;
- if (!daa_load(&bytes, board))
- return 0;
- if (!SCI_Prepare(board))
- return 0;
- bytes.high = 0x00;
- bytes.low = j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_1[7];
- if (!daa_load(&bytes, board))
- return 0;
- bytes.high = j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_1[6];
- bytes.low = j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_1[5];
- if (!daa_load(&bytes, board))
- return 0;
- bytes.high = j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_1[4];
- bytes.low = j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_1[3];
- if (!daa_load(&bytes, board))
- return 0;
- bytes.high = j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_1[2];
- bytes.low = j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_1[1];
- if (!daa_load(&bytes, board))
- return 0;
- bytes.high = j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_1[0];
- bytes.low = 0x00;
- if (!daa_load(&bytes, board))
- return 0;
- if (!SCI_Control(board, SCI_End))
- return 0;
- if (!SCI_WaitLowSCI(board))
- return 0;
- bytes.high = 0x01;
- bytes.low = j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_2[7];
- if (!daa_load(&bytes, board))
- return 0;
- bytes.high = j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_2[6];
- bytes.low = j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_2[5];
- if (!daa_load(&bytes, board))
- return 0;
- bytes.high = j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_2[4];
- bytes.low = j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_2[3];
- if (!daa_load(&bytes, board))
- return 0;
- bytes.high = j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_2[2];
- bytes.low = j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_2[1];
- if (!daa_load(&bytes, board))
- return 0;
- bytes.high = j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_2[0];
- bytes.low = 0x00;
- if (!daa_load(&bytes, board))
- return 0;
- if (!SCI_Control(board, SCI_End))
- return 0;
- if (!SCI_WaitLowSCI(board))
- return 0;
- bytes.high = 0x02;
- bytes.low = j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_3[7];
- if (!daa_load(&bytes, board))
- return 0;
- bytes.high = j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_3[6];
- bytes.low = j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_3[5];
- if (!daa_load(&bytes, board))
- return 0;
- bytes.high = j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_3[4];
- bytes.low = j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_3[3];
- if (!daa_load(&bytes, board))
- return 0;
- bytes.high = j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_3[2];
- bytes.low = j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_3[1];
- if (!daa_load(&bytes, board))
- return 0;
- bytes.high = j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_3[0];
- bytes.low = 0x00;
- if (!daa_load(&bytes, board))
- return 0;
- if (!SCI_Control(board, SCI_End))
- return 0;
- if (!SCI_WaitLowSCI(board))
- return 0;
- bytes.high = 0x03;
- bytes.low = j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_1[7];
- if (!daa_load(&bytes, board))
- return 0;
- bytes.high = j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_1[6];
- bytes.low = j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_1[5];
- if (!daa_load(&bytes, board))
- return 0;
- bytes.high = j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_1[4];
- bytes.low = j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_1[3];
- if (!daa_load(&bytes, board))
- return 0;
- bytes.high = j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_1[2];
- bytes.low = j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_1[1];
- if (!daa_load(&bytes, board))
- return 0;
- bytes.high = j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_1[0];
- bytes.low = 0x00;
- if (!daa_load(&bytes, board))
- return 0;
- if (!SCI_Control(board, SCI_End))
- return 0;
- if (!SCI_WaitLowSCI(board))
- return 0;
- bytes.high = 0x04;
- bytes.low = j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_1[7];
- if (!daa_load(&bytes, board))
- return 0;
- bytes.high = j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_1[6];
- bytes.low = j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_1[5];
- if (!daa_load(&bytes, board))
- return 0;
- bytes.high = j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_1[4];
- bytes.low = j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_1[3];
- if (!daa_load(&bytes, board))
- return 0;
- bytes.high = j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_1[2];
- bytes.low = j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_1[1];
- if (!daa_load(&bytes, board))
- return 0;
- bytes.high = j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_1[0];
- bytes.low = 0x00;
- if (!daa_load(&bytes, board))
- return 0;
- if (!SCI_Control(board, SCI_End))
- return 0;
- if (!SCI_WaitLowSCI(board))
- return 0;
- bytes.high = 0x05;
- bytes.low = j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_2[7];
- if (!daa_load(&bytes, board))
- return 0;
- bytes.high = j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_2[6];
- bytes.low = j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_2[5];
- if (!daa_load(&bytes, board))
- return 0;
- bytes.high = j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_2[4];
- bytes.low = j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_2[3];
- if (!daa_load(&bytes, board))
- return 0;
- bytes.high = j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_2[2];
- bytes.low = j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_2[1];
- if (!daa_load(&bytes, board))
- return 0;
- bytes.high = j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_2[0];
- bytes.low = 0x00;
- if (!daa_load(&bytes, board))
- return 0;
- if (!SCI_Control(board, SCI_End))
- return 0;
- if (!SCI_WaitLowSCI(board))
- return 0;
- bytes.high = 0x06;
- bytes.low = j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_2[7];
- if (!daa_load(&bytes, board))
- return 0;
- bytes.high = j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_2[6];
- bytes.low = j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_2[5];
- if (!daa_load(&bytes, board))
- return 0;
- bytes.high = j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_2[4];
- bytes.low = j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_2[3];
- if (!daa_load(&bytes, board))
- return 0;
- bytes.high = j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_2[2];
- bytes.low = j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_2[1];
- if (!daa_load(&bytes, board))
- return 0;
- bytes.high = j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_2[0];
- bytes.low = 0x00;
- if (!daa_load(&bytes, board))
- return 0;
- if (!SCI_Control(board, SCI_End))
- return 0;
- if (!SCI_WaitLowSCI(board))
- return 0;
- bytes.high = 0x07;
- bytes.low = j->m_DAAShadowRegs.COP_REGS.COP.FRRFilterCoeff[7];
- if (!daa_load(&bytes, board))
- return 0;
- bytes.high = j->m_DAAShadowRegs.COP_REGS.COP.FRRFilterCoeff[6];
- bytes.low = j->m_DAAShadowRegs.COP_REGS.COP.FRRFilterCoeff[5];
- if (!daa_load(&bytes, board))
- return 0;
- bytes.high = j->m_DAAShadowRegs.COP_REGS.COP.FRRFilterCoeff[4];
- bytes.low = j->m_DAAShadowRegs.COP_REGS.COP.FRRFilterCoeff[3];
- if (!daa_load(&bytes, board))
- return 0;
- bytes.high = j->m_DAAShadowRegs.COP_REGS.COP.FRRFilterCoeff[2];
- bytes.low = j->m_DAAShadowRegs.COP_REGS.COP.FRRFilterCoeff[1];
- if (!daa_load(&bytes, board))
- return 0;
- bytes.high = j->m_DAAShadowRegs.COP_REGS.COP.FRRFilterCoeff[0];
- bytes.low = 0x00;
- if (!daa_load(&bytes, board))
- return 0;
- if (!SCI_Control(board, SCI_End))
- return 0;
- if (!SCI_WaitLowSCI(board))
- return 0;
- bytes.high = 0x08;
- bytes.low = j->m_DAAShadowRegs.COP_REGS.COP.FRXFilterCoeff[7];
- if (!daa_load(&bytes, board))
- return 0;
- bytes.high = j->m_DAAShadowRegs.COP_REGS.COP.FRXFilterCoeff[6];
- bytes.low = j->m_DAAShadowRegs.COP_REGS.COP.FRXFilterCoeff[5];
- if (!daa_load(&bytes, board))
- return 0;
- bytes.high = j->m_DAAShadowRegs.COP_REGS.COP.FRXFilterCoeff[4];
- bytes.low = j->m_DAAShadowRegs.COP_REGS.COP.FRXFilterCoeff[3];
- if (!daa_load(&bytes, board))
- return 0;
- bytes.high = j->m_DAAShadowRegs.COP_REGS.COP.FRXFilterCoeff[2];
- bytes.low = j->m_DAAShadowRegs.COP_REGS.COP.FRXFilterCoeff[1];
- if (!daa_load(&bytes, board))
- return 0;
- bytes.high = j->m_DAAShadowRegs.COP_REGS.COP.FRXFilterCoeff[0];
- bytes.low = 0x00;
- if (!daa_load(&bytes, board))
- return 0;
- if (!SCI_Control(board, SCI_End))
- return 0;
- if (!SCI_WaitLowSCI(board))
- return 0;
- bytes.high = 0x09;
- bytes.low = j->m_DAAShadowRegs.COP_REGS.COP.ARFilterCoeff[3];
- if (!daa_load(&bytes, board))
- return 0;
- bytes.high = j->m_DAAShadowRegs.COP_REGS.COP.ARFilterCoeff[2];
- bytes.low = j->m_DAAShadowRegs.COP_REGS.COP.ARFilterCoeff[1];
- if (!daa_load(&bytes, board))
- return 0;
- bytes.high = j->m_DAAShadowRegs.COP_REGS.COP.ARFilterCoeff[0];
- bytes.low = 0x00;
- if (!daa_load(&bytes, board))
- return 0;
- if (!SCI_Control(board, SCI_End))
- return 0;
- if (!SCI_WaitLowSCI(board))
- return 0;
- bytes.high = 0x0A;
- bytes.low = j->m_DAAShadowRegs.COP_REGS.COP.AXFilterCoeff[3];
- if (!daa_load(&bytes, board))
- return 0;
- bytes.high = j->m_DAAShadowRegs.COP_REGS.COP.AXFilterCoeff[2];
- bytes.low = j->m_DAAShadowRegs.COP_REGS.COP.AXFilterCoeff[1];
- if (!daa_load(&bytes, board))
- return 0;
- bytes.high = j->m_DAAShadowRegs.COP_REGS.COP.AXFilterCoeff[0];
- bytes.low = 0x00;
- if (!daa_load(&bytes, board))
- return 0;
- if (!SCI_Control(board, SCI_End))
- return 0;
- if (!SCI_WaitLowSCI(board))
- return 0;
- bytes.high = 0x0B;
- bytes.low = j->m_DAAShadowRegs.COP_REGS.COP.Tone1Coeff[3];
- if (!daa_load(&bytes, board))
- return 0;
- bytes.high = j->m_DAAShadowRegs.COP_REGS.COP.Tone1Coeff[2];
- bytes.low = j->m_DAAShadowRegs.COP_REGS.COP.Tone1Coeff[1];
- if (!daa_load(&bytes, board))
- return 0;
- bytes.high = j->m_DAAShadowRegs.COP_REGS.COP.Tone1Coeff[0];
- bytes.low = 0x00;
- if (!daa_load(&bytes, board))
- return 0;
- if (!SCI_Control(board, SCI_End))
- return 0;
- if (!SCI_WaitLowSCI(board))
- return 0;
- bytes.high = 0x0C;
- bytes.low = j->m_DAAShadowRegs.COP_REGS.COP.Tone2Coeff[3];
- if (!daa_load(&bytes, board))
- return 0;
- bytes.high = j->m_DAAShadowRegs.COP_REGS.COP.Tone2Coeff[2];
- bytes.low = j->m_DAAShadowRegs.COP_REGS.COP.Tone2Coeff[1];
- if (!daa_load(&bytes, board))
- return 0;
- bytes.high = j->m_DAAShadowRegs.COP_REGS.COP.Tone2Coeff[0];
- bytes.low = 0x00;
- if (!daa_load(&bytes, board))
- return 0;
- if (!SCI_Control(board, SCI_End))
- return 0;
- if (!SCI_WaitLowSCI(board))
- return 0;
- bytes.high = 0x0D;
- bytes.low = j->m_DAAShadowRegs.COP_REGS.COP.LevelmeteringRinging[3];
- if (!daa_load(&bytes, board))
- return 0;
- bytes.high = j->m_DAAShadowRegs.COP_REGS.COP.LevelmeteringRinging[2];
- bytes.low = j->m_DAAShadowRegs.COP_REGS.COP.LevelmeteringRinging[1];
- if (!daa_load(&bytes, board))
- return 0;
- bytes.high = j->m_DAAShadowRegs.COP_REGS.COP.LevelmeteringRinging[0];
- bytes.low = 0x00;
- if (!daa_load(&bytes, board))
- return 0;
- if (!SCI_Control(board, SCI_End))
- return 0;
- if (!SCI_WaitLowSCI(board))
- return 0;
- bytes.high = 0x0E;
- bytes.low = j->m_DAAShadowRegs.COP_REGS.COP.CallerID1stTone[7];
- if (!daa_load(&bytes, board))
- return 0;
- bytes.high = j->m_DAAShadowRegs.COP_REGS.COP.CallerID1stTone[6];
- bytes.low = j->m_DAAShadowRegs.COP_REGS.COP.CallerID1stTone[5];
- if (!daa_load(&bytes, board))
- return 0;
- bytes.high = j->m_DAAShadowRegs.COP_REGS.COP.CallerID1stTone[4];
- bytes.low = j->m_DAAShadowRegs.COP_REGS.COP.CallerID1stTone[3];
- if (!daa_load(&bytes, board))
- return 0;
- bytes.high = j->m_DAAShadowRegs.COP_REGS.COP.CallerID1stTone[2];
- bytes.low = j->m_DAAShadowRegs.COP_REGS.COP.CallerID1stTone[1];
- if (!daa_load(&bytes, board))
- return 0;
- bytes.high = j->m_DAAShadowRegs.COP_REGS.COP.CallerID1stTone[0];
- bytes.low = 0x00;
- if (!daa_load(&bytes, board))
- return 0;
- if (!SCI_Control(board, SCI_End))
- return 0;
- if (!SCI_WaitLowSCI(board))
- return 0;
- bytes.high = 0x0F;
- bytes.low = j->m_DAAShadowRegs.COP_REGS.COP.CallerID2ndTone[7];
- if (!daa_load(&bytes, board))
- return 0;
- bytes.high = j->m_DAAShadowRegs.COP_REGS.COP.CallerID2ndTone[6];
- bytes.low = j->m_DAAShadowRegs.COP_REGS.COP.CallerID2ndTone[5];
- if (!daa_load(&bytes, board))
- return 0;
- bytes.high = j->m_DAAShadowRegs.COP_REGS.COP.CallerID2ndTone[4];
- bytes.low = j->m_DAAShadowRegs.COP_REGS.COP.CallerID2ndTone[3];
- if (!daa_load(&bytes, board))
- return 0;
- bytes.high = j->m_DAAShadowRegs.COP_REGS.COP.CallerID2ndTone[2];
- bytes.low = j->m_DAAShadowRegs.COP_REGS.COP.CallerID2ndTone[1];
- if (!daa_load(&bytes, board))
- return 0;
- bytes.high = j->m_DAAShadowRegs.COP_REGS.COP.CallerID2ndTone[0];
- bytes.low = 0x00;
- if (!daa_load(&bytes, board))
- return 0;
- udelay(32);
- j->pld_scrr.byte = inb_p(j->XILINXbase);
- if (!SCI_Control(board, SCI_End))
- return 0;
- return 1;
- }
- int ixj_set_tone_off(unsigned short arg, int board)
- {
- ixj[board].tone_off_time = arg;
- if (ixj_WriteDSPCommand(0x6E05, board)) // Set Tone Off Period
- return -1;
- if (ixj_WriteDSPCommand(arg, board))
- return -1;
- return 0;
- }
- static int ixj_get_tone_on(int board)
- {
- if (ixj_WriteDSPCommand(0x6E06, board)) // Get Tone On Period
- return -1;
- return 0;
- }
- static int ixj_get_tone_off(int board)
- {
- if (ixj_WriteDSPCommand(0x6E07, board)) // Get Tone Off Period
- return -1;
- return 0;
- }
- static void ixj_busytone(int board)
- {
- ixj[board].flags.ringback = 0;
- ixj[board].flags.dialtone = 0;
- ixj[board].flags.busytone = 1;
- ixj_set_tone_on(0x07D0, board);
- ixj_set_tone_off(0x07D0, board);
- ixj_play_tone(board, 27);
- }
- static void ixj_dialtone(int board)
- {
- ixj[board].flags.ringback = 0;
- ixj[board].flags.dialtone = 1;
- ixj[board].flags.busytone = 0;
- if (ixj[board].dsp.low == 0x20) {
- return;
- } else {
- ixj_set_tone_on(0xFFFF, board);
- ixj_set_tone_off(0x0000, board);
- ixj_play_tone(board, 25);
- }
- }
- static void ixj_cpt_stop(board)
- {
- IXJ *j = &ixj[board];
- j->flags.dialtone = 0;
- j->flags.busytone = 0;
- j->flags.ringback = 0;
- ixj_set_tone_on(0x0001, board);
- ixj_set_tone_off(0x0000, board);
- ixj_play_tone(board, 0);
- j->tone_state = 0;
- if (j->cadence_t) {
- if (j->cadence_t->ce) {
- kfree(j->cadence_t->ce);
- }
- kfree(j->cadence_t);
- j->cadence_t = NULL;
- }
- if (j->dsp.low == 0x20 || (j->play_mode == -1 && j->rec_mode == -1))
- idle(board);
- if (j->play_mode != -1)
- ixj_play_start(board);
- if (j->rec_mode != -1)
- ixj_record_start(board);
- }
- static void ixj_ringback(int board)
- {
- ixj[board].flags.busytone = 0;
- ixj[board].flags.dialtone = 0;
- ixj[board].flags.ringback = 1;
- ixj_set_tone_on(0x0FA0, board);
- ixj_set_tone_off(0x2EE0, board);
- ixj_play_tone(board, 26);
- }
- static void ixj_testram(int board)
- {
- ixj_WriteDSPCommand(0x3001, board); /* Test External SRAM */
- }
- static int ixj_build_cadence(int board, IXJ_CADENCE * cp)
- {
- IXJ_CADENCE *lcp;
- IXJ_CADENCE_ELEMENT *lcep;
- IXJ_TONE ti;
- IXJ *j = &ixj[board];
- lcp = kmalloc(sizeof(IXJ_CADENCE), GFP_KERNEL);
- if (lcp == NULL)
- return -ENOMEM;
- if (copy_from_user(lcp, (char *) cp, sizeof(IXJ_CADENCE)))
- return -EFAULT;
- lcep = kmalloc(sizeof(IXJ_CADENCE_ELEMENT) * lcp->elements_used, GFP_KERNEL);
- if (lcep == NULL) {
- kfree(lcp);
- return -ENOMEM;
- }
- if (copy_from_user(lcep, lcp->ce, sizeof(IXJ_CADENCE_ELEMENT) * lcp->elements_used))
- return -EFAULT;
- if (j->cadence_t) {
- kfree(j->cadence_t->ce);
- kfree(j->cadence_t);
- }
- lcp->ce = (void *) lcep;
- j->cadence_t = lcp;
- j->tone_cadence_state = 0;
- ixj_set_tone_on(lcp->ce[0].tone_on_time, board);
- ixj_set_tone_off(lcp->ce[0].tone_off_time, board);
- if (j->cadence_t->ce[j->tone_cadence_state].freq0) {
- ti.tone_index = j->cadence_t->ce[j->tone_cadence_state].index;
- ti.freq0 = j->cadence_t->ce[j->tone_cadence_state].freq0;
- ti.gain0 = j->cadence_t->ce[j->tone_cadence_state].gain0;
- ti.freq1 = j->cadence_t->ce[j->tone_cadence_state].freq1;
- ti.gain1 = j->cadence_t->ce[j->tone_cadence_state].gain1;
- ixj_init_tone(board, &ti);
- }
- ixj_play_tone(board, lcp->ce[0].index);
- return 1;
- }
- static int ixj_build_filter_cadence(int board, IXJ_FILTER_CADENCE * cp)
- {
- IXJ_FILTER_CADENCE *lcp;
- IXJ *j = &ixj[board];
- lcp = kmalloc(sizeof(IXJ_CADENCE), GFP_KERNEL);
- if (lcp == NULL)
- return -ENOMEM;
- if (copy_from_user(lcp, (char *) cp, sizeof(IXJ_FILTER_CADENCE)))
- return -EFAULT;
- if (lcp->filter > 4)
- return -1;
- j->cadence_f[lcp->filter].state = 0;
- j->cadence_f[lcp->filter].enable = lcp->enable;
- j->cadence_f[lcp->filter].on1 = lcp->on1;
- j->cadence_f[lcp->filter].on1min = 0;
- j->cadence_f[lcp->filter].on1max = 0;
- j->cadence_f[lcp->filter].off1 = lcp->off1;
- j->cadence_f[lcp->filter].off1min = 0;
- j->cadence_f[lcp->filter].off1max = 0;
- j->cadence_f[lcp->filter].on2 = lcp->on2;
- j->cadence_f[lcp->filter].on2min = 0;
- j->cadence_f[lcp->filter].on2max = 0;
- j->cadence_f[lcp->filter].off2 = lcp->off2;
- j->cadence_f[lcp->filter].off2min = 0;
- j->cadence_f[lcp->filter].off2max = 0;
- j->cadence_f[lcp->filter].on3 = lcp->on3;
- j->cadence_f[lcp->filter].on3min = 0;
- j->cadence_f[lcp->filter].on3max = 0;
- j->cadence_f[lcp->filter].off3 = lcp->off3;
- j->cadence_f[lcp->filter].off3min = 0;
- j->cadence_f[lcp->filter].off3max = 0;
- kfree(lcp);
- return 0;
- }
- static void add_caps(int board)
- {
- IXJ *j = &ixj[board];
- j->caps = 0;
- j->caplist[j->caps].cap = PHONE_VENDOR_QUICKNET;
- strcpy(j->caplist[j->caps].desc, "Quicknet Technologies, Inc. (www.quicknet.net)");
- j->caplist[j->caps].captype = vendor;
- j->caplist[j->caps].handle = j->caps++;
- j->caplist[j->caps].captype = device;
- switch (j->cardtype) {
- case 100:
- strcpy(j->caplist[j->caps].desc, "Quicknet Internet PhoneJACK");
- j->caplist[j->caps].cap = 100;
- break;
- case 300:
- strcpy(j->caplist[j->caps].desc, "Quicknet Internet LineJACK");
- j->caplist[j->caps].cap = 300;
- break;
- case 400:
- strcpy(j->caplist[j->caps].desc, "Quicknet Internet PhoneJACK Lite");
- j->caplist[j->caps].cap = 400;
- break;
- case 500:
- strcpy(j->caplist[j->caps].desc, "Quicknet Internet PhoneJACK PCI");
- j->caplist[j->caps].cap = 500;
- break;
- }
- j->caplist[j->caps].handle = j->caps++;
- strcpy(j->caplist[j->caps].desc, "POTS");
- j->caplist[j->caps].captype = port;
- j->caplist[j->caps].cap = pots;
- j->caplist[j->caps].handle = j->caps++;
- switch (ixj[board].cardtype) {
- case 100:
- strcpy(j->caplist[j->caps].desc, "SPEAKER");
- j->caplist[j->caps].captype = port;
- j->caplist[j->caps].cap = speaker;
- j->caplist[j->caps].handle = j->caps++;
- strcpy(j->caplist[j->caps].desc, "HANDSET");
- j->caplist[j->caps].captype = port;
- j->caplist[j->caps].cap = handset;
- j->caplist[j->caps].handle = j->caps++;
- break;
- case 300:
- strcpy(j->caplist[j->caps].desc, "SPEAKER");
- j->caplist[j->caps].captype = port;
- j->caplist[j->caps].cap = speaker;
- j->caplist[j->caps].handle = j->caps++;
- strcpy(j->caplist[j->caps].desc, "PSTN");
- j->caplist[j->caps].captype = port;
- j->caplist[j->caps].cap = pstn;
- j->caplist[j->caps].handle = j->caps++;
- break;
- }
- strcpy(j->caplist[j->caps].desc, "ULAW");
- j->caplist[j->caps].captype = codec;
- j->caplist[j->caps].cap = ULAW;
- j->caplist[j->caps].handle = j->caps++;
- strcpy(j->caplist[j->caps].desc, "LINEAR 16 bit");
- j->caplist[j->caps].captype = codec;
- j->caplist[j->caps].cap = LINEAR16;
- j->caplist[j->caps].handle = j->caps++;
- strcpy(j->caplist[j->caps].desc, "LINEAR 8 bit");
- j->caplist[j->caps].captype = codec;
- j->caplist[j->caps].cap = LINEAR8;
- j->caplist[j->caps].handle = j->caps++;
- strcpy(j->caplist[j->caps].desc, "Windows Sound System");
- j->caplist[j->caps].captype = codec;
- j->caplist[j->caps].cap = WSS;
- j->caplist[j->caps].handle = j->caps++;
- if (j->ver.low != 0x12) {
- strcpy(j->caplist[j->caps].desc, "G.723.1 6.3Kbps");
- j->caplist[j->caps].captype = codec;
- j->caplist[j->caps].cap = G723_63;
- j->caplist[j->caps].handle = j->caps++;
- strcpy(j->caplist[j->caps].desc, "G.723.1 5.3Kbps");
- j->caplist[j->caps].captype = codec;
- j->caplist[j->caps].cap = G723_53;
- j->caplist[j->caps].handle = j->caps++;
- strcpy(j->caplist[j->caps].desc, "TrueSpeech 4.8Kbps");
- j->caplist[j->caps].captype = codec;
- j->caplist[j->caps].cap = TS48;
- j->caplist[j->caps].handle = j->caps++;
- strcpy(j->caplist[j->caps].desc, "TrueSpeech 4.1Kbps");
- j->caplist[j->caps].captype = codec;
- j->caplist[j->caps].cap = TS41;
- j->caplist[j->caps].handle = j->caps++;
- }
- if (j->cardtype == 100) {
- strcpy(j->caplist[j->caps].desc, "TrueSpeech 8.5Kbps");
- j->caplist[j->caps].captype = codec;
- j->caplist[j->caps].cap = TS85;
- j->caplist[j->caps].handle = j->caps++;
- }
- }
- static int capabilities_check(int board, struct phone_capability *pcreq)
- {
- int cnt;
- IXJ *j = &ixj[board];
- int retval = 0;
- for (cnt = 0; cnt < j->caps; cnt++) {
- if (pcreq->captype == j->caplist[cnt].captype &&
- pcreq->cap == j->caplist[cnt].cap) {
- retval = 1;
- break;
- }
- }
- return retval;
- }
- int ixj_ioctl(struct inode *inode, struct file *file_p,
- unsigned int cmd, unsigned long arg)
- {
- IXJ_TONE ti;
- IXJ_FILTER jf;
- unsigned int minor = MINOR(inode->i_rdev);
- int board = NUM(inode->i_rdev);
- IXJ *j = &ixj[NUM(inode->i_rdev)];
- int retval = 0;
- if (ixjdebug > 1)
- printk(KERN_DEBUG "phone%d ioctl, cmd: 0x%x, arg: 0x%lxn", minor, cmd, arg);
- if (minor >= IXJMAX)
- return -ENODEV;
- /*
- * Check ioctls only root can use.
- */
- if (!capable(CAP_SYS_ADMIN)) {
- switch (cmd) {
- case IXJCTL_TESTRAM:
- case IXJCTL_HZ:
- return -EPERM;
- }
- }
- switch (cmd) {
- case IXJCTL_TESTRAM:
- ixj_testram(board);
- retval = (j->ssr.high << 8) + j->ssr.low;
- break;
- case IXJCTL_CARDTYPE:
- retval = j->cardtype;
- break;
- case IXJCTL_SERIAL:
- retval = j->serial;
- break;
- case PHONE_RING_CADENCE:
- j->ring_cadence = arg;
- break;
- case PHONE_RING_START:
- ixj_ring_start(board);
- break;
- case PHONE_RING_STOP:
- j->flags.cringing = 0;
- ixj_ring_off(board);
- break;
- case PHONE_RING:
- retval = ixj_ring(board);
- break;
- case PHONE_EXCEPTION:
- retval = j->ex.bytes;
- j->ex.bytes &= 0x03;
- break;
- case PHONE_HOOKSTATE:
- j->ex.bits.hookstate = 0;
- retval = j->r_hook;
- break;
- case IXJCTL_SET_LED:
- LED_SetState(arg, board);
- break;
- case PHONE_FRAME:
- retval = set_base_frame(board, arg);
- break;
- case PHONE_REC_CODEC:
- retval = set_rec_codec(board, arg);
- break;
- case PHONE_VAD:
- ixj_vad(board, arg);
- break;
- case PHONE_REC_START:
- ixj_record_start(board);
- break;
- case PHONE_REC_STOP:
- ixj_record_stop(board);
- break;
- case PHONE_REC_DEPTH:
- set_rec_depth(board, arg);
- break;
- case PHONE_REC_VOLUME:
- set_rec_volume(board, arg);
- break;
- case PHONE_REC_LEVEL:
- retval = get_rec_level(board);
- break;
- case IXJCTL_AEC_START:
- ixj_aec_start(board, arg);
- break;
- case IXJCTL_AEC_STOP:
- aec_stop(board);
- break;
- case IXJCTL_AEC_GET_LEVEL:
- retval = j->aec_level;
- break;
- case PHONE_PLAY_CODEC:
- retval = set_play_codec(board, arg);
- break;
- case PHONE_PLAY_START:
- ixj_play_start(board);
- break;
- case PHONE_PLAY_STOP:
- ixj_play_stop(board);
- break;
- case PHONE_PLAY_DEPTH:
- set_play_depth(board, arg);
- break;
- case PHONE_PLAY_VOLUME:
- set_play_volume(board, arg);
- break;
- case PHONE_PLAY_LEVEL:
- retval = get_play_level(board);
- break;
- case IXJCTL_DSP_TYPE:
- retval = (j->dsp.high << 8) + j->dsp.low;
- break;
- case IXJCTL_DSP_VERSION:
- retval = (j->ver.high << 8) + j->ver.low;
- break;
- case IXJCTL_HZ:
- hertz = arg;
- break;
- case IXJCTL_RATE:
- if (arg > hertz)
- retval = -1;
- else
- samplerate = arg;
- break;
- case IXJCTL_DRYBUFFER_READ:
- put_user(j->drybuffer, (unsigned long *) arg);
- break;
- case IXJCTL_DRYBUFFER_CLEAR:
- j->drybuffer = 0;
- break;
- case IXJCTL_FRAMES_READ:
- put_user(j->framesread, (unsigned long *) arg);
- break;
- case IXJCTL_FRAMES_WRITTEN:
- put_user(j->frameswritten, (unsigned long *) arg);
- break;
- case IXJCTL_READ_WAIT:
- put_user(j->read_wait, (unsigned long *) arg);
- break;
- case IXJCTL_WRITE_WAIT:
- put_user(j->write_wait, (unsigned long *) arg);
- break;
- case PHONE_MAXRINGS:
- j->maxrings = arg;
- break;
- case PHONE_SET_TONE_ON_TIME:
- ixj_set_tone_on(arg, board);
- break;
- case PHONE_SET_TONE_OFF_TIME:
- ixj_set_tone_off(arg, board);
- break;
- case PHONE_GET_TONE_ON_TIME:
- if (ixj_get_tone_on(board)) {
- retval = -1;
- } else {
- retval = (j->ssr.high << 8) + j->ssr.low;
- }
- break;
- case PHONE_GET_TONE_OFF_TIME:
- if (ixj_get_tone_off(board)) {
- retval = -1;
- } else {
- retval = (j->ssr.high << 8) + j->ssr.low;
- }
- break;
- case PHONE_PLAY_TONE:
- if (!j->tone_state)
- ixj_play_tone(board, arg);
- break;
- case PHONE_GET_TONE_STATE:
- retval = j->tone_state;
- break;
- case PHONE_DTMF_READY:
- retval = j->ex.bits.dtmf_ready;
- break;
- case PHONE_GET_DTMF:
- if (ixj_hookstate(board)) {
- if (j->dtmf_rp != j->dtmf_wp) {
- retval = j->dtmfbuffer[j->dtmf_rp];
- j->dtmf_rp++;
- if (j->dtmf_rp == 79)
- j->dtmf_rp = 0;
- if (j->dtmf_rp == j->dtmf_wp) {
- j->ex.bits.dtmf_ready = j->dtmf_rp = j->dtmf_wp = 0;
- }
- }
- }
- break;
- case PHONE_GET_DTMF_ASCII:
- if (ixj_hookstate(board)) {
- if (j->dtmf_rp != j->dtmf_wp) {
- switch (j->dtmfbuffer[j->dtmf_rp]) {
- case 10:
- retval = 42; //'*';
- break;
- case 11:
- retval = 48; //'0';
- break;
- case 12:
- retval = 35; //'#';
- break;
- case 28:
- retval = 65; //'A';
- break;
- case 29:
- retval = 66; //'B';
- break;
- case 30:
- retval = 67; //'C';
- break;
- case 31:
- retval = 68; //'D';
- break;
- default:
- retval = 48 + j->dtmfbuffer[j->dtmf_rp];
- break;
- }
- j->dtmf_rp++;
- if (j->dtmf_rp == 79)
- j->dtmf_rp = 0;
- // if(j->dtmf_rp == j->dtmf_wp)
- {
- j->ex.bits.dtmf_ready = j->dtmf_rp = j->dtmf_wp = 0;
- }
- }
- }
- break;
- case PHONE_DTMF_OOB:
- j->flags.dtmf_oob = arg;
- break;
- case PHONE_DIALTONE:
- ixj_dialtone(board);
- break;
- case PHONE_BUSY:
- ixj_busytone(board);
- break;
- case PHONE_RINGBACK:
- ixj_ringback(board);
- break;
- case PHONE_CPT_STOP:
- ixj_cpt_stop(board);
- break;
- case IXJCTL_DSP_IDLE:
- idle(board);
- break;
- case IXJCTL_MIXER:
- ixj_mixer(arg, board);
- break;
- case IXJCTL_DAA_COEFF_SET:
- switch (arg) {
- case DAA_US:
- DAA_Coeff_US(board);
- retval = ixj_daa_write(board);
- break;
- case DAA_UK:
- DAA_Coeff_UK(board);
- retval = ixj_daa_write(board);
- break;
- case DAA_FRANCE:
- DAA_Coeff_France(board);
- retval = ixj_daa_write(board);
- break;
- case DAA_GERMANY:
- DAA_Coeff_Germany(board);
- retval = ixj_daa_write(board);
- break;
- case DAA_AUSTRALIA:
- DAA_Coeff_Australia(board);
- retval = ixj_daa_write(board);
- break;
- case DAA_JAPAN:
- DAA_Coeff_Japan(board);
- retval = ixj_daa_write(board);
- break;
- default:
- retval = 1;
- break;
- }
- break;
- case IXJCTL_DAA_AGAIN:
- ixj_daa_cr4(board, arg | 0x02);
- break;
- case IXJCTL_PSTN_LINETEST:
- retval = ixj_linetest(board);
- break;
- case IXJCTL_CID:
- if (copy_to_user((char *) arg, &j->cid, sizeof(IXJ_CID)))
- return -EFAULT;
- j->ex.bits.caller_id = 0;
- break;
- case IXJCTL_WINK_DURATION:
- j->winktime = arg;
- break;
- case IXJCTL_PORT:
- if (arg)
- retval = ixj_set_port(board, arg);
- else
- retval = j->port;
- break;
- case IXJCTL_POTS_PSTN:
- retval = ixj_set_pots(board, arg);
- break;
- case PHONE_CAPABILITIES:
- retval = j->caps;
- break;
- case PHONE_CAPABILITIES_LIST:
- if (copy_to_user((char *) arg, j->caplist, sizeof(struct phone_capability) * j->caps))
- return -EFAULT;
- break;
- case PHONE_CAPABILITIES_CHECK:
- retval = capabilities_check(board, (struct phone_capability *) arg);
- break;