/* * Wildcard TDM2400P TDM FXS/FXO Interface Driver for DAHDI Telephony interface * * Written by Mark Spencer * Support for TDM800P and VPM150M by Matthew Fredrickson * * 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 #include #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,26) #include #else #include #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_QRV 5 #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_SLOTS 6 #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 #define VPM150M_SUPPORT #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 usecount; 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]; /* 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; /* for schluffen() */ 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]; int modtype[NUM_MODULES]; /* type of module (FXO/FXS/QRV/etc.) */ int sethook[NUM_MODULES]; /* pending hook state command */ int dacssrc[NUM_MODULES]; struct vpmadt032 *vpmadt032; 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 schluffen(wait_queue_head_t *q); void wait_just_a_bit(int foo); 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