?? ixj-redhat.c
字號:
/** * 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 funtionsstatic 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 ModelHost address Function AccessDSPbase +0-1 Aux Software Status Register (reserved) Read Only2-3 Software Status Register Read Only4-5 Aux Software Control Register (reserved) Read Write6-7 Software Control Register Read Write8-9 Hardware Status Register Read OnlyA-B Hardware Control Register Read WriteC-D Host Transmit (Write) Data Buffer Access Port (buffer input)Write OnlyE-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;
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -