8c24b0fd8f
If we're waiting for tens or hundreds of milliseconds we will just go to sleep instead of spinning. Signed-off-by: Shaun Ruffell <sruffell@digium.com> git-svn-id: http://svn.asterisk.org/svn/dahdi/linux/trunk@9471 a0bf4364-ded3-4de4-8d8a-66a801d63aff
295 lines
7.6 KiB
C
295 lines
7.6 KiB
C
/*
|
|
* Wildcard TDM2400P TDM FXS/FXO Interface Driver for DAHDI Telephony interface
|
|
*
|
|
* Written by Mark Spencer <markster@digium.com>
|
|
* Support for TDM800P and VPM150M by Matthew Fredrickson <creslin@digium.com>
|
|
*
|
|
* Copyright (C) 2005-2010 Digium, Inc.
|
|
*
|
|
* All rights reserved.
|
|
*
|
|
*/
|
|
|
|
/*
|
|
* See http://www.asterisk.org for more information about
|
|
* the Asterisk project. Please do not directly contact
|
|
* any of the maintainers of this project for assistance;
|
|
* the project provides a web site, mailing lists and IRC
|
|
* channels for your use.
|
|
*
|
|
* This program is free software, distributed under the terms of
|
|
* the GNU General Public License Version 2 as published by the
|
|
* Free Software Foundation. See the LICENSE file included with
|
|
* this program for more details.
|
|
*/
|
|
|
|
#ifndef _WCTDM24XXP_H
|
|
#define _WCTDM24XXP_H
|
|
|
|
#include <dahdi/kernel.h>
|
|
|
|
#include <linux/version.h>
|
|
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,26)
|
|
#include <linux/semaphore.h>
|
|
#else
|
|
#include <asm/semaphore.h>
|
|
#endif
|
|
|
|
#include "voicebus/voicebus.h"
|
|
|
|
#define NUM_FXO_REGS 60
|
|
|
|
#define WC_MAX_IFACES 128
|
|
|
|
/*!
|
|
* \brief Default ringer debounce (in ms)
|
|
*/
|
|
#define DEFAULT_RING_DEBOUNCE 1024
|
|
|
|
#define POLARITY_DEBOUNCE 64 /* Polarity debounce (in ms) */
|
|
|
|
#define OHT_TIMER 6000 /* How long after RING to retain OHT */
|
|
|
|
#define FLAG_3215 (1 << 0)
|
|
#define FLAG_EXPRESS (1 << 1)
|
|
|
|
#define EFRAME_SIZE 108L
|
|
#define EFRAME_GAP 20L
|
|
#define SFRAME_SIZE ((EFRAME_SIZE * DAHDI_CHUNKSIZE) + (EFRAME_GAP * (DAHDI_CHUNKSIZE - 1)))
|
|
|
|
#define MAX_ALARMS 10
|
|
|
|
#define MOD_TYPE_NONE 0
|
|
#define MOD_TYPE_FXS 1
|
|
#define MOD_TYPE_FXO 2
|
|
#define MOD_TYPE_FXSINIT 3
|
|
#define MOD_TYPE_VPM 4
|
|
#define MOD_TYPE_QRV 5
|
|
#define MOD_TYPE_VPM150M 6
|
|
#define MOD_TYPE_BRI 7
|
|
|
|
#define MINPEGTIME 10 * 8 /* 30 ms peak to peak gets us no more than 100 Hz */
|
|
#define PEGTIME 50 * 8 /* 50ms peak to peak gets us rings of 10 Hz or more */
|
|
#define PEGCOUNT 5 /* 5 cycles of pegging means RING */
|
|
|
|
#define SDI_CLK (0x00010000)
|
|
#define SDI_DOUT (0x00020000)
|
|
#define SDI_DREAD (0x00040000)
|
|
#define SDI_DIN (0x00080000)
|
|
|
|
#define __CMD_RD (1 << 20) /* Read Operation */
|
|
#define __CMD_WR (1 << 21) /* Write Operation */
|
|
#define __CMD_FIN (1 << 22) /* Has finished receive */
|
|
#define __CMD_TX (1 << 23) /* Has been transmitted */
|
|
|
|
#define CMD_WR(a,b) (((a) << 8) | (b) | __CMD_WR)
|
|
#define CMD_RD(a) (((a) << 8) | __CMD_RD)
|
|
|
|
#if 0
|
|
#define CMD_BYTE(card,bit,altcs) (((((card) & 0x3) * 3 + (bit)) * 7) \
|
|
+ ((card) >> 2) + (altcs) + ((altcs) ? -21 : 0))
|
|
#endif
|
|
#define NUM_MODULES 24
|
|
#define NUM_EC 4
|
|
#define NUM_SLOTS 6
|
|
#define MAX_TDM_CHAN 31
|
|
#define MAX_SPANS 9
|
|
|
|
#define NUM_CAL_REGS 12
|
|
|
|
#define USER_COMMANDS 8
|
|
#define ISR_COMMANDS 2
|
|
#define QRV_DEBOUNCETIME 20
|
|
|
|
#define MAX_COMMANDS (USER_COMMANDS + ISR_COMMANDS)
|
|
|
|
#define VPM150M_HPI_CONTROL 0x00
|
|
#define VPM150M_HPI_ADDRESS 0x02
|
|
#define VPM150M_HPI_DATA 0x03
|
|
|
|
#define VPM_SUPPORT
|
|
|
|
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
|
|
#define VPM150M_SUPPORT
|
|
#endif
|
|
|
|
#ifdef VPM_SUPPORT
|
|
|
|
/* Define to get more attention-grabbing but slightly more CPU using echocan status */
|
|
#define FANCY_ECHOCAN
|
|
|
|
#endif
|
|
|
|
#ifdef VPM150M_SUPPORT
|
|
#include "voicebus/GpakCust.h"
|
|
#endif
|
|
|
|
struct calregs {
|
|
unsigned char vals[NUM_CAL_REGS];
|
|
};
|
|
|
|
struct cmdq {
|
|
unsigned int cmds[MAX_COMMANDS];
|
|
unsigned char isrshadow[ISR_COMMANDS];
|
|
};
|
|
|
|
enum battery_state {
|
|
BATTERY_UNKNOWN = 0,
|
|
BATTERY_PRESENT,
|
|
BATTERY_LOST,
|
|
};
|
|
|
|
/**
|
|
* struct wctdm_span -
|
|
* @span: dahdi_span to register.
|
|
* @timing_priority: What the priority of this span is relative to the other
|
|
* spans.
|
|
* @spanno: Which span on the card this is.
|
|
*
|
|
* NOTE: spanno would normally be taken care of by dahdi_span.offset, but
|
|
* appears to have meaning in xhfc.c, and that needs to be audited before
|
|
* changing. !!!TODO!!!
|
|
*
|
|
*/
|
|
struct wctdm_span {
|
|
struct dahdi_span span;
|
|
int timing_priority;
|
|
int spanno;
|
|
struct wctdm *wc;
|
|
struct b400m_span *bspan;
|
|
};
|
|
|
|
struct wctdm_chan {
|
|
struct dahdi_chan chan;
|
|
struct dahdi_echocan_state ec;
|
|
int timeslot;
|
|
};
|
|
|
|
struct wctdm {
|
|
const struct wctdm_desc *desc;
|
|
char board_name[80];
|
|
int pos; /* card number in system */
|
|
|
|
spinlock_t frame_list_lock;
|
|
struct list_head frame_list;
|
|
|
|
unsigned int intcount;
|
|
unsigned char txident;
|
|
unsigned char rxident;
|
|
|
|
int flags[NUM_MODULES]; /* bitmap of board-specific + module-specific flags */
|
|
unsigned char ctlreg; /* FIXME: something to do with VPM? */
|
|
|
|
int mods_per_board; /* maximum number of modules for this board */
|
|
int digi_mods; /* number of digital modules present */
|
|
int avchannels; /* active "voice" (voice, B and D) channels */
|
|
int modmap; /* Bit-map of present cards (1=present) */
|
|
|
|
int altcs[NUM_MODULES + NUM_EC];
|
|
|
|
/* FIXME: why are all of these QRV-only members part of the main card structure? */
|
|
char qrvhook[NUM_MODULES];
|
|
unsigned short qrvdebtime[NUM_MODULES];
|
|
int radmode[NUM_MODULES];
|
|
#define RADMODE_INVERTCOR 1
|
|
#define RADMODE_IGNORECOR 2
|
|
#define RADMODE_EXTTONE 4
|
|
#define RADMODE_EXTINVERT 8
|
|
#define RADMODE_IGNORECT 16
|
|
#define RADMODE_PREEMP 32
|
|
#define RADMODE_DEEMP 64
|
|
unsigned short debouncetime[NUM_MODULES];
|
|
signed short rxgain[NUM_MODULES];
|
|
signed short txgain[NUM_MODULES];
|
|
|
|
spinlock_t reglock; /* held when accessing anything affecting the module array */
|
|
wait_queue_head_t regq;
|
|
|
|
union {
|
|
struct fxo {
|
|
int wasringing;
|
|
int lastrdtx;
|
|
int lastrdtx_count;
|
|
int ringdebounce;
|
|
int offhook;
|
|
int battdebounce;
|
|
int battalarm;
|
|
enum battery_state battery;
|
|
int lastpol;
|
|
int polarity;
|
|
int polaritydebounce;
|
|
int neonmwi_state;
|
|
int neonmwi_last_voltage;
|
|
unsigned int neonmwi_debounce;
|
|
unsigned int neonmwi_offcounter;
|
|
} fxo;
|
|
struct fxs {
|
|
int oldrxhook;
|
|
int debouncehook;
|
|
int lastrxhook;
|
|
int debounce;
|
|
int ohttimer;
|
|
int idletxhookstate; /* IDLE changing hook state */
|
|
/* lasttxhook reflects the last value written to the proslic's reg
|
|
* 64 (LINEFEED_CONTROL) in bits 0-2. Bit 4 indicates if the last
|
|
* write is pending i.e. it is in process of being written to the
|
|
* register
|
|
* NOTE: in order for this value to actually be written to the
|
|
* proslic, the appropriate matching value must be written into the
|
|
* sethook variable so that it gets queued and handled by the
|
|
* voicebus ISR.
|
|
*/
|
|
int lasttxhook;
|
|
int oppending_ms;
|
|
spinlock_t lasttxhooklock;
|
|
int palarms;
|
|
struct dahdi_vmwi_info vmwisetting;
|
|
int vmwi_active_messages;
|
|
int vmwi_linereverse;
|
|
int reversepolarity; /* polarity reversal */
|
|
struct calregs calregs;
|
|
} fxs;
|
|
struct b400m *bri;
|
|
} mods[NUM_MODULES];
|
|
|
|
struct cmdq cmdq[NUM_MODULES + NUM_EC];
|
|
int modtype[NUM_MODULES + NUM_EC]; /* type of module (FXO/FXS/QRV/VPM/etc.) in this position */
|
|
int sethook[NUM_MODULES + NUM_EC]; /* pending hook state command for each module */
|
|
int dacssrc[NUM_MODULES];
|
|
|
|
int vpm100;
|
|
|
|
struct vpmadt032 *vpmadt032;
|
|
#ifdef FANCY_ECHOCAN
|
|
int echocanpos;
|
|
int blinktimer;
|
|
#endif
|
|
struct voicebus vb;
|
|
struct wctdm_span *aspan; /* pointer to the spans[] holding the analog span */
|
|
struct wctdm_span *spans[MAX_SPANS];
|
|
struct wctdm_chan *chans[NUM_MODULES];
|
|
#ifdef CONFIG_VOICEBUS_ECREFERENCE
|
|
struct dahdi_fifo *ec_reference[NUM_MODULES];
|
|
#endif
|
|
|
|
/* Only care about digital spans here */
|
|
/* int span_timing_prio[MAX_SPANS - 1]; */
|
|
struct semaphore syncsem;
|
|
int oldsync;
|
|
|
|
int initialized; /* =1 when the entire card is ready to go */
|
|
unsigned long checkflag; /* Internal state flags and task bits */
|
|
int companding;
|
|
};
|
|
|
|
/* Atomic flag bits for checkflag field */
|
|
#define WCTDM_CHECK_TIMING 0
|
|
|
|
int wctdm_getreg(struct wctdm *wc, int card, int addr);
|
|
int wctdm_setreg(struct wctdm *wc, int card, int addr, int val);
|
|
|
|
extern struct semaphore ifacelock;
|
|
extern struct wctdm *ifaces[WC_MAX_IFACES];
|
|
|
|
#endif
|