wanpipe/patches/kdrivers/src/net/sdla_8te1.c

5542 lines
153 KiB
C

/*
* Copyright (c) 2006
* Alex Feldman <al.feldman@sangoma.com>. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by Alex Feldman.
* 4. Neither the name of the author nor the names of any co-contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY Alex Feldman AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL Alex Feldman OR THE VOICES IN HIS HEAD
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGE.
*
* $Id: sdla_8te1.c,v 1.121 2008-04-25 16:23:20 sangoma Exp $
*/
/******************************************************************************
** sdla_8te1.c WANPIPE(tm) Multiprotocol WAN Link Driver.
** 8 ports T1/E1 board configuration.
**
** Author: Alex Feldman <al.feldman@sangoma.com>
**
** ============================================================================
** Date Name Label Description
** ============================================================================
** 02-18-06 Alex Feldman Initial version.
** 07-10-07 Alex Feldman EBIT Enable auto E-bit support.
** Nov 23, 2007 Alex Feldman UNFRM Add support E1 Unframe mode for E1
** interface.
** Nov 23, 2007 Alex Feldman TXTRI Add support for TX Tri-state.
** Feb 06, 2008 Alex Feldman E1_120 Adjust waveform for E1, 120 ohm.
******************************************************************************/
/******************************************************************************
* INCLUDE FILES
******************************************************************************/
# include "wanpipe_includes.h"
# include "wanpipe_defines.h"
# include "wanpipe_debug.h"
# include "wanproc.h"
# if !defined(CONFIG_PRODUCT_WANPIPE_GENERIC)
# include "wanpipe_snmp.h"
# endif
# include "sdla_te1_ds.h"
# include "wanpipe.h" /* WANPIPE common user API definitions */
/******************************************************************************
* DEFINES AND MACROS
******************************************************************************/
#define WAN_TE1_DEVICE_ID DEVICE_ID_DS(READ_REG_LINE(0, REG_IDR))
#define CLEAR_REG(sreg,ereg) { \
unsigned short reg; \
for(reg = sreg; reg < ereg; reg++){ \
WRITE_REG(reg, 0x00); \
} \
}
#define IS_GLREG(reg) ((reg) >= 0xF0 && (reg) <= 0xFF)
#define IS_FRREG(reg) ((reg) <= 0x1F0)
#define IS_LIUREG(reg) ((reg) >= 0x1000 && (reg) <= 0x101F)
#define IS_BERTREG(reg) ((reg) >= 0x1100 && (reg) <= 0x110F)
#define DLS_PORT_DELTA(reg) \
IS_GLREG(reg) ? 0x000 : \
IS_FRREG(reg) ? 0x200 : \
IS_LIUREG(reg) ? 0x020 : \
IS_BERTREG(reg) ? 0x010 : 0x001
/* Read/Write to front-end register */
#define WRITE_REG(reg,val) \
fe->write_fe_reg( \
((sdla_t*)fe->card)->hw, \
(int)(((sdla_t*)fe->card)->wandev.state==WAN_CONNECTED), \
(int)fe->fe_cfg.line_no, \
(int)sdla_ds_te1_address(fe,fe->fe_cfg.line_no,(reg)), \
(int)(val))
#define WRITE_REG_LINE(fe_line_no, reg,val) \
fe->write_fe_reg( \
((sdla_t*)fe->card)->hw, \
(int)(((sdla_t*)fe->card)->wandev.state==WAN_CONNECTED), \
(int)fe_line_no, \
(int)sdla_ds_te1_address(fe,fe_line_no,(reg)), \
(int)(val))
#define READ_REG(reg) \
fe->read_fe_reg( \
((sdla_t*)fe->card)->hw, \
(int)(((sdla_t*)fe->card)->wandev.state==WAN_CONNECTED), \
(int)fe->fe_cfg.line_no, \
(int)sdla_ds_te1_address(fe,fe->fe_cfg.line_no,(reg)))
#define __READ_REG(reg) \
fe->__read_fe_reg( \
((sdla_t*)fe->card)->hw, \
(int)(((sdla_t*)fe->card)->wandev.state==WAN_CONNECTED), \
(int)fe->fe_cfg.line_no, \
(int)sdla_ds_te1_address(fe,fe->fe_cfg.line_no,(reg)))
#define READ_REG_LINE(fe_line_no, reg) \
fe->read_fe_reg( \
((sdla_t*)fe->card)->hw, \
(int)(((sdla_t*)fe->card)->wandev.state==WAN_CONNECTED), \
(int)fe_line_no, \
(int)sdla_ds_te1_address(fe,fe_line_no,(reg)))
#define WAN_T1_FRAMED_ALARMS (WAN_TE_BIT_ALARM_RED | WAN_TE_BIT_ALARM_LOF)
#define WAN_E1_FRAMED_ALARMS (WAN_TE_BIT_ALARM_RED | WAN_TE_BIT_ALARM_LOF) // | WAN_TE_BIT_ALARM_LIU_LOS)
/*Nov 23, 2007 UNFRM */
#define WAN_TE1_UNFRAMED_ALARMS (WAN_TE_BIT_ALARM_RED | \
WAN_TE_BIT_ALARM_LOS)
#define IS_T1_ALARM(alarm) \
(alarm & \
( \
WAN_TE_BIT_ALARM_RED | \
WAN_TE_BIT_ALARM_AIS | \
WAN_TE_BIT_ALARM_LOF | \
WAN_TE_BIT_ALARM_LOS | \
WAN_TE_BIT_ALARM_ALOS \
))
#define IS_E1_ALARM(alarm) \
(alarm & \
( \
WAN_TE_BIT_ALARM_RED | \
WAN_TE_BIT_ALARM_AIS | \
WAN_TE_BIT_ALARM_OOF | \
WAN_TE_BIT_ALARM_LOS | \
WAN_TE_BIT_ALARM_ALOS \
))
#define WAN_DS_REGBITMAP(fe) (((fe)->fe_chip_id==DEVICE_ID_DS26521)?0:WAN_FE_LINENO((fe)))
/******************************************************************************
* STRUCTURES AND TYPEDEFS
******************************************************************************/
/******************************************************************************
* GLOBAL VERIABLES
******************************************************************************/
char *wan_t1_ds_rxlevel[] = {
"> -2.5db",
"-2.5db to -5db",
"-5db to -7.5db",
"-7.5db to -10db",
"-10db to -12.5db",
"-12.5db to -15db",
"-15db to -17.5db",
"-17.5db to -20db",
"-20db to -23db",
"-23db to -26db",
"-26db to -29db",
"-29db to -32db",
"-32db to -36db",
"< -36db",
"",
""
};
char *wan_e1_ds_rxlevel[] = {
"> -2.5db",
"-2.5db to -5db",
"-5db to -7.5db",
"-7.5db to -10db",
"-10db to -12.5db",
"-12.5db to -15db",
"-15db to -17.5db",
"-17.5db to -20db",
"-20db to -23db",
"-23db to -26db",
"-26db to -29db",
"-29db to -32db",
"-32db to -36db",
"-36db to -40db",
"-40db to -44db",
"< -44db"
};
/******************************************************************************
* FUNCTION PROTOTYPES
******************************************************************************/
static int sdla_ds_te1_reset(void* pfe, int port_no, int reset);
static int sdla_ds_te1_global_config(void* pfe); /* Change to static */
static int sdla_ds_te1_global_unconfig(void* pfe); /* Change to static */
static int sdla_ds_te1_chip_config(void* pfe);
/*static int sdla_ds_te1_chip_config_verify(sdla_fe_t* pfe);*/
static int sdla_ds_te1_config(void* pfe); /* Change to static */
static int sdla_ds_te1_reconfig(sdla_fe_t* fe);
static int sdla_ds_te1_post_init(void *pfe);
static int sdla_ds_te1_unconfig(void* pfe); /* Change to static */
static int sdla_ds_te1_pre_release(void* pfe);
static int sdla_ds_te1_TxChanCtrl(sdla_fe_t* fe, int channel, int enable);
static int sdla_ds_te1_RxChanCtrl(sdla_fe_t* fe, int channel, int enable);
static int sdla_ds_te1_disable_irq(void* pfe); /* Change to static */
static int sdla_ds_te1_intr_ctrl(sdla_fe_t*, int, u_int8_t, u_int8_t, unsigned int);
static int sdla_ds_te1_check_intr(sdla_fe_t *fe);
static int sdla_ds_te1_intr(sdla_fe_t *fe);
static int sdla_ds_te1_udp(sdla_fe_t *fe, void* p_udp_cmd, unsigned char* data);
static int sdla_ds_te1_flush_pmon(sdla_fe_t *fe);
static int sdla_ds_te1_pmon(sdla_fe_t *fe, int action);
static int sdla_ds_te1_rxlevel(sdla_fe_t* fe);
static int sdla_ds_te1_polling(sdla_fe_t* fe);
static int sdla_ds_te1_update_alarms(sdla_fe_t*, u_int32_t);
static unsigned int sdla_ds_te1_read_alarms(sdla_fe_t *fe, int read);
static int sdla_ds_te1_set_alarms(sdla_fe_t* fe, u_int32_t alarms);
static int sdla_ds_te1_clear_alarms(sdla_fe_t* fe, u_int32_t alarms);
static int sdla_ds_te1_set_status(sdla_fe_t* fe, u_int32_t alarms);
static int sdla_ds_te1_print_alarms(sdla_fe_t*, unsigned int);
static int sdla_ds_te1_set_lb(sdla_fe_t*, u_int8_t, u_int8_t, u_int32_t);
static int sdla_ds_te1_rbs_init(sdla_fe_t* fe);
static int sdla_ds_te1_rbs_update(sdla_fe_t* fe, int, unsigned char);
static int sdla_ds_te1_set_rbsbits(sdla_fe_t *fe, int, unsigned char);
static int sdla_ds_te1_rbs_report(sdla_fe_t* fe);
static int sdla_ds_te1_check_rbsbits(sdla_fe_t* fe, int, unsigned int, int);
static unsigned char sdla_ds_te1_read_rbsbits(sdla_fe_t* fe, int, int);
static int sdla_ds_te1_add_event(sdla_fe_t*, sdla_fe_timer_event_t*);
static int sdla_ds_te1_add_timer(sdla_fe_t*, unsigned long);
//static void sdla_ds_te1_enable_timer(sdla_fe_t*, unsigned char, unsigned long);
static int sdla_ds_te1_sigctrl(sdla_fe_t *fe, int, unsigned long, int);
#if defined(__NetBSD__) || defined(__FreeBSD__) || defined(__OpenBSD__)
static void sdla_ds_te1_timer(void* pfe);
#elif defined(__WINDOWS__)
static void sdla_ds_te1_timer(IN PKDPC Dpc, void* pfe, void* arg2, void* arg3);
#else
static void sdla_ds_te1_timer(unsigned long pfe);
#endif
static int sdla_ds_te1_swirq_trigger(sdla_fe_t* fe, int type, int subtype, int delay);
static int sdla_ds_te1_swirq_link(sdla_fe_t* fe);
static int sdla_ds_te1_swirq_alarm(sdla_fe_t* fe, int type);
static int sdla_ds_te1_swirq(sdla_fe_t* fe);
static int sdla_ds_te1_update_alarm_info(sdla_fe_t*, struct seq_file*, int*);
static int sdla_ds_te1_update_pmon_info(sdla_fe_t*, struct seq_file*, int*);
static int sdla_ds_te1_txlbcode_done(sdla_fe_t *fe);
static int sdla_ds_te1_boc(sdla_fe_t *fe, int mode);
static int sdla_ds_te1_liu_rlb(sdla_fe_t* fe, unsigned char cmd);
static int sdla_ds_te1_fr_plb(sdla_fe_t* fe, unsigned char cmd);
static int sdla_ds_te1_pclb(sdla_fe_t*, u_int8_t, u_int32_t);
static int sdla_ds_te1_bert_read_status(sdla_fe_t *fe);
static int sdla_ds_te1_bert_status(sdla_fe_t *fe, sdla_te_bert_stats_t *);
static int sdla_ds_e1_sa6code(sdla_fe_t* fe);
static int sdla_ds_e1_sabits(sdla_fe_t* fe);
/******************************************************************************
* FUNCTION DEFINITIONS
******************************************************************************/
/******************************************************************************
* sdla_te3_get_fe_status()
*
* Description:
* Arguments:
* Returns:
******************************************************************************
*/
static char* sdla_ds_te1_get_fe_media_string(void)
{
return ("AFT-A108 T1/E1");
}
/******************************************************************************
* sdla_ds_te1_get_fe_status()
*
* Description:
* Arguments:
* Returns:
******************************************************************************
*/
static unsigned char sdla_ds_te1_get_fe_media(sdla_fe_t *fe)
{
return fe->fe_cfg.media;
}
/******************************************************************************
* sdla_ds_te1_get_fe_status()
*
* Description : Get current FE line state - is it Connected or Disconnected
*
* Arguments : fe - pointer to Front End structure.
* status - pointer to location where the FE line state will
* be stored.
* notused - ignored
*
* Returns : always zero.
*******************************************************************************/
static int sdla_ds_te1_get_fe_status(sdla_fe_t *fe, unsigned char *status,int notused)
{
*status = fe->fe_status;
return 0;
}
/******************************************************************************
* sdla_te1_ds_te1_address()
*
* Description:
* Arguments:
* Returns:
******************************************************************************
*/
static int sdla_ds_te1_address(sdla_fe_t *fe, int port_no, int reg)
{
/* for a102, replace port number of second chip to 1 (1->0) */
if (fe->fe_chip_id == DEVICE_ID_DS26521){
port_no = 0;
}
return (int)((reg) + ((port_no)*(DLS_PORT_DELTA(reg))));
}
/*
******************************************************************************
* sdla_ds_te1_TxChanCtrl()
*
* Description:
* Arguments:
* Returns:
******************************************************************************
*/
static int sdla_ds_te1_TxChanCtrl(sdla_fe_t* fe, int channel, int enable)
{
int off = channel / 8;
int bit = channel % 8;
unsigned char value;
value = READ_REG(REG_TGCCS1 + off);
if (enable){
value &= ~(1 << (bit-1));
}else{
value |= (1 << (bit-1));
}
WRITE_REG(REG_TGCCS1 + off, value);
return 0;
}
/*
******************************************************************************
* sdla_ds_te1_RxChanCtrl()
*
* Description:
* Arguments:
* Returns:
******************************************************************************
*/
static int sdla_ds_te1_RxChanCtrl(sdla_fe_t* fe, int channel, int enable)
{
int off = channel / 8;
int bit = channel % 8;
unsigned char value;
value = READ_REG(REG_RGCCS1 + off);
if (enable){
value &= ~(1 << (bit-1));
}else{
value |= (1 << (bit-1));
}
WRITE_REG(REG_RGCCS1 + off, value);
return 0;
}
int sdla_ds_te1_iface_init(void *p_fe, void *p_fe_iface)
{
sdla_fe_t *fe = (sdla_fe_t*)p_fe;
sdla_fe_iface_t *fe_iface = (sdla_fe_iface_t*)p_fe_iface;
fe_iface->reset = &sdla_ds_te1_reset;
fe_iface->global_config = &sdla_ds_te1_global_config;
fe_iface->global_unconfig = &sdla_ds_te1_global_unconfig;
fe_iface->chip_config = &sdla_ds_te1_chip_config;
fe_iface->config = &sdla_ds_te1_config;
fe_iface->post_init = &sdla_ds_te1_post_init;
fe_iface->reconfig = &sdla_ds_te1_reconfig;
fe_iface->unconfig = &sdla_ds_te1_unconfig;
fe_iface->pre_release = &sdla_ds_te1_pre_release;
fe_iface->disable_irq = &sdla_ds_te1_disable_irq;
fe_iface->isr = &sdla_ds_te1_intr;
fe_iface->check_isr = &sdla_ds_te1_check_intr;
fe_iface->intr_ctrl = &sdla_ds_te1_intr_ctrl;
fe_iface->polling = &sdla_ds_te1_polling;
fe_iface->process_udp = &sdla_ds_te1_udp;
fe_iface->print_fe_alarm = &sdla_ds_te1_print_alarms;
/*fe_iface->print_fe_act_channels = &sdla_te_print_channels;*/
fe_iface->read_alarm = &sdla_ds_te1_read_alarms;
/*fe_iface->set_fe_alarm = &sdla_te_set_alarms;*/
fe_iface->read_pmon = &sdla_ds_te1_pmon;
fe_iface->flush_pmon = &sdla_ds_te1_flush_pmon;
fe_iface->get_fe_status = &sdla_ds_te1_get_fe_status;
fe_iface->get_fe_media = &sdla_ds_te1_get_fe_media;
fe_iface->get_fe_media_string = &sdla_ds_te1_get_fe_media_string;
fe_iface->update_alarm_info = &sdla_ds_te1_update_alarm_info;
fe_iface->update_pmon_info = &sdla_ds_te1_update_pmon_info;
fe_iface->set_fe_lbmode = &sdla_ds_te1_set_lb;
fe_iface->read_rbsbits = &sdla_ds_te1_read_rbsbits;
fe_iface->check_rbsbits = &sdla_ds_te1_check_rbsbits;
fe_iface->report_rbsbits = &sdla_ds_te1_rbs_report;
fe_iface->set_rbsbits = &sdla_ds_te1_set_rbsbits;
fe_iface->set_fe_sigctrl = &sdla_ds_te1_sigctrl;
#if 0
fe_iface->led_ctrl = &sdla_te_led_ctrl;
#endif
/* Initial FE state */
fe->fe_status = FE_UNITIALIZED; //FE_DISCONNECTED;
WAN_LIST_INIT(&fe->event);
wan_spin_lock_irq_init(&fe->lockirq, "wan_8te1_lock");
return 0;
}
/******************************************************************************
* sdla_ds_te1_device_id()
*
* Description: Verify device id
* Arguments:
* Returns: 0 - device is supported, otherwise - device is not supported
******************************************************************************/
static int sdla_ds_te1_device_id(sdla_fe_t* fe)
{
// u_int8_t value;
/* Revision/Chip ID (Reg. 0x0D) */
// value = READ_REG_LINE(0, REG_IDR);
// fe->fe_chip_id = DEVICE_ID_DS(value);
fe->fe_chip_id = WAN_TE1_DEVICE_ID;
switch(fe->fe_chip_id){
case DEVICE_ID_DS26528:
fe->fe_max_ports = 8;
break;
case DEVICE_ID_DS26524:
fe->fe_max_ports = 4;
break;
case DEVICE_ID_DS26521:
fe->fe_max_ports = 1;
break;
case DEVICE_ID_DS26522:
fe->fe_max_ports = 2;
break;
default:
DEBUG_EVENT("%s: ERROR: Unsupported DS %s CHIP (%02X:%02X)\n",
fe->name,
FE_MEDIA_DECODE(fe),
fe->fe_chip_id,
READ_REG_LINE(0, REG_IDR));
return -EINVAL;
}
return 0;
}
/*
******************************************************************************
* sdla_ds_te1_reset()
*
* Description: Global configuration for Sangoma TE1 DS board.
* Note: These register should be program only once for AFT-QUAD
* cards.
* Arguments: fe - front-end structure
* port_no - 0 - global set/clear reset, 1-8 - set/clear reset per port
* reset - 0 - clear reset, 1 - set reset
* Returns: WANTRUE - TE1 configred successfully, otherwise WAN_FALSE.
******************************************************************************
*/
static int sdla_ds_te1_reset(void* pfe, int port_no, int reset)
{
sdla_fe_t *fe = (sdla_fe_t*)pfe;
u_int8_t mask = 0x00, value, liu_status, fr_be_status;
if (sdla_ds_te1_device_id(fe)) return -EINVAL;
if (port_no){
DEBUG_EVENT("%s: %s Front End Reset for port %d\n",
fe->name,
(reset) ? "Set" : "Clear",
port_no);
}else{
DEBUG_EVENT("%s: %s Global Front End Reset\n",
fe->name, (reset) ? "Set" : "Clear");
}
if (port_no){
mask = (0x01 << WAN_DS_REGBITMAP(fe));
}else{
int i = 0;
mask = 0x00;
for(i=0;i<fe->fe_max_ports;i++){
mask |= (1<<i);
}
}
/* Set reset first */
liu_status = READ_REG(REG_GLSRR);
liu_status |= mask;
WRITE_REG(REG_GLSRR, liu_status);
fr_be_status = READ_REG(REG_GFSRR);
fr_be_status |= mask;
WRITE_REG(REG_GFSRR, fr_be_status);
if (fe->fe_chip_id == DEVICE_ID_DS26521 && !port_no){
value = READ_REG_LINE(1, REG_GLSRR);
value |= 0x01;
WRITE_REG_LINE(1, REG_GLSRR, value);
value = READ_REG_LINE(1, REG_GFSRR);
value |= 0x01;
WRITE_REG_LINE(1, REG_GFSRR, value);
}
if (!reset){
WP_DELAY(1000);
/* Clear reset */
liu_status &= ~mask;
WRITE_REG(REG_GLSRR, liu_status);
fr_be_status &= ~mask;
WRITE_REG(REG_GFSRR, fr_be_status);
if (fe->fe_chip_id == DEVICE_ID_DS26521 && !port_no){
value = READ_REG_LINE(1, REG_GLSRR);
value &= ~0x01;
WRITE_REG_LINE(1, REG_GLSRR, value);
value = READ_REG_LINE(1, REG_GFSRR);
value &= ~0x01;
WRITE_REG_LINE(1, REG_GFSRR, value);
}
}
return 0;
}
/*
******************************************************************************
* sdla_ds_e1_set_sig_mode()
*
* Description: Set E1 signalling mode for A101/A102/A104/A108 DallasMaxim board.
* Arguments:
* Returns:
******************************************************************************
*/
static int sdla_ds_e1_set_sig_mode(sdla_fe_t *fe, int verbose)
{
unsigned char value = 0x00;
if (WAN_TE1_SIG_MODE(fe) == WAN_TE1_SIG_CAS){
/* CAS signalling mode */
if (verbose){
DEBUG_EVENT("%s: Enable E1 CAS Signalling mode!\n",
fe->name);
}
value = READ_REG(REG_RCR1);
WRITE_REG(REG_RCR1, value & ~BIT_RCR1_E1_RSIGM);
//value = READ_REG(REG_RSIGC);
//WRITE_REG(REG_RSIGC, value | BIT_RSIGC_CASMS);
value = READ_REG(REG_TCR1);
WRITE_REG(REG_TCR1, value | BIT_TCR1_E1_T16S);
}else{
/* CCS signalling mode */
if (verbose){
DEBUG_EVENT("%s: Enable E1 CCS Signalling mode!\n",
fe->name);
}
WAN_TE1_SIG_MODE(fe) = WAN_TE1_SIG_CCS;
value = READ_REG(REG_RCR1);
WRITE_REG(REG_RCR1, value | BIT_RCR1_E1_RSIGM);
value = READ_REG(REG_TCR1);
WRITE_REG(REG_TCR1, value & ~BIT_TCR1_E1_T16S);
}
return 0;
}
/*
******************************************************************************
* sdla_8te_global_config()
*
* Description: Global configuration for Sangoma TE1 DS board.
* Note: These register should be program only once for AFT-OCTAL
* cards.
* Arguments:
* Returns: WANTRUE - TE1 configred successfully, otherwise WAN_FALSE.
******************************************************************************
*/
static int sdla_ds_te1_global_config(void* pfe)
{
sdla_fe_t *fe = (sdla_fe_t*)pfe;
if (sdla_ds_te1_device_id(fe)) return -EINVAL;
DEBUG_EVENT("%s: Global %s Front End configuration\n",
fe->name, FE_MEDIA_DECODE(fe));
WRITE_REG_LINE(0, REG_GTCCR, 0x00);
WRITE_REG_LINE(0, REG_GTCR1, 0x00);
WRITE_REG_LINE(0, REG_GLSRR, 0xFF);
WRITE_REG_LINE(0, REG_GFSRR, 0xFF);
WP_DELAY(1000);
WRITE_REG_LINE(0, REG_GLSRR, 0x00);
WRITE_REG_LINE(0, REG_GFSRR, 0x00);
return 0;
}
/*
******************************************************************************
* sdla_ds_te1_global_unconfig()
*
* Description: Global configuration for Sangoma TE1 DS board.
* Note: These register should be program only once for AFT-QUAD
* cards.
* Arguments:
* Returns: WANTRUE - TE1 configred successfully, otherwise WAN_FALSE.
******************************************************************************
*/
static int sdla_ds_te1_global_unconfig(void* pfe)
{
sdla_fe_t *fe = (sdla_fe_t*)pfe;
DEBUG_EVENT("%s: Global %s Front End unconfigation!\n",
fe->name, FE_MEDIA_DECODE(fe));
WRITE_REG_LINE(0, REG_GFIMR, 0x00);
WRITE_REG_LINE(0, REG_GLIMR, 0x00);
WRITE_REG_LINE(0, REG_GBIMR, 0x00);
WP_DELAY(1000);
WRITE_REG_LINE(0, REG_GLSRR, 0xFF);
WRITE_REG_LINE(0, REG_GFSRR, 0xFF);
WP_DELAY(1000);
return 0;
}
/******************************************************************************
** sdla_ds_t1_cfg_verify()
**
** Description: Verify T1 Front-End configuration
** Arguments:
** Returns: 0 - successfully, otherwise -EINVAL.
*******************************************************************************/
static int sdla_ds_t1_cfg_verify(void* pfe)
{
sdla_fe_t *fe = (sdla_fe_t*)pfe;
/* Verify FE framing type */
switch(WAN_FE_FRAME(fe)){
case WAN_FR_D4: case WAN_FR_ESF: case WAN_FR_UNFRAMED:
break;
case WAN_FR_NONE:
DEBUG_EVENT("%s: Defaulting T1 Frame = ESF\n",
fe->name);
WAN_FE_FRAME(fe) = WAN_FR_ESF;
break;
default:
DEBUG_EVENT("%s: Error: Invalid %s FE Framing type (%X)\n",
fe->name,
FE_MEDIA_DECODE(fe),
WAN_FE_FRAME(fe));
return -EINVAL;
break;
}
/* Verify FE line code type */
switch(WAN_FE_LCODE(fe)){
case WAN_LCODE_B8ZS: case WAN_LCODE_AMI:
break;
case WAN_LCODE_NONE:
DEBUG_EVENT("%s: Defaulting T1 Line Code = B8ZS\n",
fe->name);
WAN_FE_LCODE(fe) = WAN_LCODE_B8ZS;
break;
default:
DEBUG_EVENT("%s: Error: Invalid %s FE Line code type (%X)\n",
fe->name,
FE_MEDIA_DECODE(fe),
WAN_FE_LCODE(fe));
return -EINVAL;
break;
}
/* Verify LBO */
switch(WAN_TE1_LBO(fe)) {
case WAN_T1_LBO_0_DB: case WAN_T1_LBO_75_DB:
case WAN_T1_LBO_15_DB: case WAN_T1_LBO_225_DB:
case WAN_T1_0_133: case WAN_T1_0_110:
case WAN_T1_133_266: case WAN_T1_110_220:
case WAN_T1_266_399: case WAN_T1_220_330:
case WAN_T1_399_533: case WAN_T1_330_440: case WAN_T1_440_550:
case WAN_T1_533_655: case WAN_T1_550_660:
break;
case WAN_T1_LBO_NONE:
DEBUG_EVENT("%s: Defaulting T1 LBO = 0 db\n",
fe->name);
WAN_TE1_LBO(fe) = WAN_T1_LBO_0_DB;
break;
default:
DEBUG_EVENT("%s: Error: Invalid %s LBO value (%X)\n",
fe->name,
FE_MEDIA_DECODE(fe),
WAN_TE1_LBO(fe));
return -EINVAL;
break;
}
if (WAN_TE1_HI_MODE(fe)){
switch(fe->fe_cfg.cfg.te_cfg.rx_slevel){
case WAN_TE1_RX_SLEVEL_30_DB: case WAN_TE1_RX_SLEVEL_225_DB:
case WAN_TE1_RX_SLEVEL_175_DB: case WAN_TE1_RX_SLEVEL_12_DB:
break;
case WAN_TE1_RX_SLEVEL_NONE:
DEBUG_EVENT("%s: Defaulting T1 Rx Sens. Gain= 30 db\n",
fe->name);
fe->fe_cfg.cfg.te_cfg.rx_slevel = WAN_TE1_RX_SLEVEL_30_DB;
break;
default:
DEBUG_EVENT(
"%s: Error: Invalid T1 Rx Sensitivity Gain (%d).\n",
fe->name,
fe->fe_cfg.cfg.te_cfg.rx_slevel);
return -EINVAL;
}
}else{
switch(fe->fe_cfg.cfg.te_cfg.rx_slevel){
case WAN_TE1_RX_SLEVEL_36_DB: case WAN_TE1_RX_SLEVEL_30_DB:
case WAN_TE1_RX_SLEVEL_18_DB: case WAN_TE1_RX_SLEVEL_12_DB:
break;
case WAN_TE1_RX_SLEVEL_NONE:
DEBUG_EVENT("%s: Defaulting T1 Rx Sens. Gain= 36 db\n",
fe->name);
fe->fe_cfg.cfg.te_cfg.rx_slevel = WAN_TE1_RX_SLEVEL_36_DB;
break;
default:
DEBUG_EVENT(
"%s: Error: Invalid T1 Rx Sensitivity Gain (%d).\n",
fe->name,
fe->fe_cfg.cfg.te_cfg.rx_slevel);
return -EINVAL;
}
}
return 0;
}
/******************************************************************************
** sdla_ds_e1_cfg_verify()
**
** Description: Verify E1 Front-End configuration
** Arguments:
** Returns: 0 - successfully, otherwise -EINVAL.
*******************************************************************************/
static int sdla_ds_e1_cfg_verify(void* pfe)
{
sdla_fe_t *fe = (sdla_fe_t*)pfe;
/* Verify FE framing type */
switch(WAN_FE_FRAME(fe)){
case WAN_FR_NCRC4: case WAN_FR_CRC4: case WAN_FR_UNFRAMED:
break;
case WAN_FR_NONE:
DEBUG_EVENT("%s: Defaulting E1 Frame = CRC4\n",
fe->name);
WAN_FE_FRAME(fe) = WAN_FR_CRC4;
break;
default:
DEBUG_EVENT("%s: Error: Invalid %s FE Framing type (%X)\n",
fe->name,
FE_MEDIA_DECODE(fe),
WAN_FE_FRAME(fe));
return -EINVAL;
break;
}
/* Verify FE line code type */
switch(WAN_FE_LCODE(fe)){
case WAN_LCODE_HDB3: case WAN_LCODE_AMI:
break;
case WAN_LCODE_NONE:
DEBUG_EVENT("%s: Defaulting E1 Line Code = HDB3\n",
fe->name);
WAN_FE_LCODE(fe) = WAN_LCODE_HDB3;
break;
default:
DEBUG_EVENT("%s: Error: Invalid %s FE Line code type (%X)\n",
fe->name,
FE_MEDIA_DECODE(fe),
WAN_FE_LCODE(fe));
return -EINVAL;
break;
}
/* Verify LBO */
switch(WAN_TE1_LBO(fe)) {
case WAN_E1_120: case WAN_E1_75:
break;
case WAN_T1_LBO_NONE:
DEBUG_EVENT("%s: Defaulting E1 LBO = 120 OH\n",
fe->name);
WAN_TE1_LBO(fe) = WAN_E1_120;
break;
default:
DEBUG_EVENT("%s: Error: Invalid %s LBO value (%X)\n",
fe->name,
FE_MEDIA_DECODE(fe),
WAN_TE1_LBO(fe));
return -EINVAL;
break;
}
switch(WAN_TE1_SIG_MODE(fe)){
case WAN_TE1_SIG_CAS: case WAN_TE1_SIG_CCS:
break;
case WAN_TE1_SIG_NONE:
DEBUG_EVENT("%s: Defaulting E1 Signalling = CCS\n",
fe->name);
WAN_TE1_SIG_MODE(fe) = WAN_TE1_SIG_CCS;
break;
default:
DEBUG_EVENT("%s: Error: Invalid E1 Signalling type (%X)\n",
fe->name,
WAN_TE1_SIG_MODE(fe));
return -EINVAL;
break;
}
if (WAN_TE1_HI_MODE(fe)){
switch(fe->fe_cfg.cfg.te_cfg.rx_slevel){
case WAN_TE1_RX_SLEVEL_30_DB: case WAN_TE1_RX_SLEVEL_225_DB:
case WAN_TE1_RX_SLEVEL_175_DB: case WAN_TE1_RX_SLEVEL_12_DB:
break;
case WAN_TE1_RX_SLEVEL_NONE:
DEBUG_EVENT("%s: Defaulting E1 Rx Sens. Gain= 30 db\n",
fe->name);
fe->fe_cfg.cfg.te_cfg.rx_slevel = WAN_TE1_RX_SLEVEL_30_DB;
break;
default:
DEBUG_EVENT(
"%s: Error: Invalid T1 Rx Sensitivity Gain (%d).\n",
fe->name,
fe->fe_cfg.cfg.te_cfg.rx_slevel);
return -EINVAL;
}
}else{
switch(fe->fe_cfg.cfg.te_cfg.rx_slevel){
case WAN_TE1_RX_SLEVEL_43_DB: case WAN_TE1_RX_SLEVEL_30_DB:
case WAN_TE1_RX_SLEVEL_18_DB: case WAN_TE1_RX_SLEVEL_12_DB:
break;
case WAN_TE1_RX_SLEVEL_NONE:
DEBUG_EVENT("%s: Defaulting E1 Rx Sens. Gain= 43 db\n",
fe->name);
fe->fe_cfg.cfg.te_cfg.rx_slevel = WAN_TE1_RX_SLEVEL_43_DB;
break;
default:
DEBUG_EVENT(
"%s: Error: Invalid T1 Rx Sensitivity Gain (%d).\n",
fe->name,
fe->fe_cfg.cfg.te_cfg.rx_slevel);
return -EINVAL;
}
}
return 0;
}
/******************************************************************************
** sdla_ds_te1_chip_config()
**
** Description: Configure Dallas Front-End chip
** Arguments:
** Returns: 0 - successfully, otherwise -EINVAL.
*******************************************************************************/
static int sdla_ds_te1_chip_config(void* pfe)
{
sdla_fe_t *fe = (sdla_fe_t*)pfe;
unsigned char value = 0x00;
WAN_ASSERT(fe->write_fe_reg == NULL);
WAN_ASSERT(fe->read_fe_reg == NULL);
/* Init Rx Framer registers */
CLEAR_REG(0x0000, 0x00F0);
/* Init Tx Framer registers */
CLEAR_REG(0x0100, 0x01F0);
/* Init LIU registers */
CLEAR_REG(0x1000, 0x1020);
/* Init BERT registers */
CLEAR_REG(0x1100, 0x1110);
/* Set Rx Framer soft reset */
WRITE_REG(REG_RMMR, BIT_RMMR_SFTRST);
/* Set Tx Framer soft reset */
WRITE_REG(REG_TMMR, BIT_RMMR_SFTRST);
if (IS_T1_FEMEDIA(fe)){
/* Clear Rx Framer soft reset */
WRITE_REG(REG_RMMR, 0x00);
/* Clear Tx Framer soft reset */
WRITE_REG(REG_TMMR, 0x00);
/* Enable Rx Framer */
WRITE_REG(REG_RMMR, BIT_RMMR_FRM_EN);
/* Enable Tx Framer */
WRITE_REG(REG_TMMR, BIT_TMMR_FRM_EN);
}else{
/* Clear Rx Framer soft reset */
WRITE_REG(REG_RMMR, BIT_RMMR_T1E1);
/* Clear Tx Framer soft reset */
WRITE_REG(REG_TMMR, BIT_TMMR_T1E1);
/* Enable Rx Framer */
WRITE_REG(REG_RMMR, (BIT_RMMR_FRM_EN | BIT_RMMR_T1E1));
/* Enable Tx Framer */
WRITE_REG(REG_TMMR, (BIT_TMMR_FRM_EN | BIT_TMMR_T1E1));
}
if (IS_T1_FEMEDIA(fe)){
WRITE_REG(REG_RCR1, BIT_RCR1_T1_SYNCT);
}
switch(WAN_FE_FRAME(fe)){
case WAN_FR_D4:
value = READ_REG(REG_RCR1);
WRITE_REG(REG_RCR1, value | BIT_RCR1_T1_RFM/* | BIT_RCR1_T1_SYNCC*/);
value = READ_REG(REG_TCR2);
WRITE_REG(REG_TCR2, value & ~BIT_TCR2_T1_TFDLS);
value = READ_REG(REG_TCR3);
WRITE_REG(REG_TCR3, value | BIT_TCR3_TFM);
WRITE_REG(REG_T1TFDL, 0x1c);
break;
case WAN_FR_ESF:
value = READ_REG(REG_RCR1);
value |= BIT_RCR1_T1_SYNCC;
value &= ~BIT_RCR1_T1_RFM;
WRITE_REG(REG_RCR1, value);
value = READ_REG(REG_TCR3);
value &= ~BIT_TCR3_TFM;
WRITE_REG(REG_TCR3, value);
break;
case WAN_FR_SLC96:
value = READ_REG(REG_RCR1);
value |= (BIT_RCR1_T1_RFM|BIT_RCR1_T1_SYNCC);
value &= ~BIT_RCR1_T1_SYNCT;
WRITE_REG(REG_RCR1, value);
value = READ_REG(REG_T1RCR2);
WRITE_REG(REG_T1RCR2, value | BIT_T1RCR2_RSLC96);
value = READ_REG(REG_TCR1);
value &= ~BIT_TCR1_T1_TFPT;
WRITE_REG(REG_TCR1, value);
value = READ_REG(REG_TCR2);
value |= BIT_TCR2_T1_TSLC96;
value &= ~BIT_TCR2_T1_TFDLS;
WRITE_REG(REG_TCR2, value);
value = READ_REG(REG_TCR3);
WRITE_REG(REG_TCR3, value | BIT_TCR3_TFM);
break;
case WAN_FR_NCRC4:
break;
case WAN_FR_CRC4:
value = READ_REG(REG_RCR1);
WRITE_REG(REG_RCR1, value | BIT_RCR1_E1_RCRC4);
value = READ_REG(REG_TCR1);
WRITE_REG(REG_TCR1, value | BIT_TCR1_E1_TCRC4);
/* EBIT: Enable auto E-bit support */
value = READ_REG(REG_TCR2);
WRITE_REG(REG_TCR2, value | BIT_TCR2_E1_AEBE);
break;
case WAN_FR_UNFRAMED:
/* Nov 23, 2007 UNFRM */
value = READ_REG(REG_TCR1);
WRITE_REG(REG_TCR1, value | BIT_TCR1_E1_TTPT);
value = READ_REG(REG_RCR1);
WRITE_REG(REG_RCR1, value | BIT_RCR1_E1_SYNCE);
break;
default:
DEBUG_EVENT("%s: Unsupported DS Frame mode (%X)\n",
fe->name, WAN_FE_FRAME(fe));
return -EINVAL;
}
if (IS_E1_FEMEDIA(fe)){
sdla_ds_e1_set_sig_mode(fe, 0);
}
switch(WAN_FE_LCODE(fe)){
case WAN_LCODE_B8ZS:
value = READ_REG(REG_RCR1);
WRITE_REG(REG_RCR1, value | BIT_RCR1_T1_RB8ZS);
value = READ_REG(REG_TCR1);
WRITE_REG(REG_TCR1, value | BIT_TCR1_T1_TB8ZS);
break;
case WAN_LCODE_HDB3:
value = READ_REG(REG_RCR1);
WRITE_REG(REG_RCR1, value | BIT_RCR1_E1_RHDB3);
value = READ_REG(REG_TCR1);
WRITE_REG(REG_TCR1, value | BIT_TCR1_E1_THDB3);
break;
case WAN_LCODE_AMI:
if (IS_T1_FEMEDIA(fe)){
value = READ_REG(REG_RCR1);
WRITE_REG(REG_RCR1, value & ~BIT_RCR1_T1_RB8ZS);
value = READ_REG(REG_TCR1);
WRITE_REG(REG_TCR1, value & ~BIT_TCR1_T1_TB8ZS);
}else{
value = READ_REG(REG_RCR1);
WRITE_REG(REG_RCR1, value & ~BIT_RCR1_E1_RHDB3);
value = READ_REG(REG_TCR1);
WRITE_REG(REG_TCR1, value & ~BIT_TCR1_E1_THDB3);
}
break;
default:
DEBUG_EVENT("%s: Unsupported DS Line code mode (%X)\n",
fe->name, WAN_FE_LCODE(fe));
return -EINVAL;
}
/* RSYSCLK output */
WRITE_REG(REG_RIOCR, BIT_RIOCR_RSCLKM);
/* TSYSCLK input */
if (IS_T1_FEMEDIA(fe)){
WRITE_REG(REG_TIOCR, 0x00);
}else{
WRITE_REG(REG_TIOCR, BIT_TIOCR_TSCLKM);
}
#if 0
if (WAN_TE1_CLK(fe) == WAN_MASTER_CLK){
/* RSYNC as input */
value = READ_REG(REG_RIOCR);
value |= BIT_RIOCR_RSIO;
WRITE_REG(REG_RIOCR, value);
/* RESE enable */
value = READ_REG(REG_RESCR);
value |= BIT_RESCR_RESE;
WRITE_REG(REG_RESCR, value);
/* TSYNC as output */
value = READ_REG(REG_TIOCR);
value |= BIT_TIOCR_TSIO;
WRITE_REG(REG_TIOCR, value);
}
#endif
if (IS_E1_FEMEDIA(fe)){
//WRITE_REG(REG_E1TAF, 0x1B);
//WRITE_REG(REG_E1TNAF, 0x40);
WRITE_REG(REG_E1TAF, 0x1B);
WRITE_REG(REG_E1TNAF, 0x5F);
WRITE_REG(REG_E1TSa4, 0x00);
WRITE_REG(REG_E1TSa5, 0x00);
WRITE_REG(REG_E1TSa6, 0x00);
WRITE_REG(REG_E1TSa7, 0x00);
WRITE_REG(REG_E1TSa8, 0x00);
WRITE_REG(REG_E1TSACR, 0x00);
if (WAN_FE_FRAME(fe) == WAN_FR_CRC4){
WRITE_REG(REG_E1TSa4, 0xFF);
WRITE_REG(REG_E1TSa5, 0xFF);
WRITE_REG(REG_E1TSa6, 0xFF);
WRITE_REG(REG_E1TSa7, 0xFF);
WRITE_REG(REG_E1TSa8, 0xFF);
WRITE_REG(REG_E1TSACR, 0x1F);
}
/* Enable Rx Sabit detection */
WRITE_REG(REG_E1RSAIMR, 0x00);
}
// FIXME: BOC
if (IS_T1_FEMEDIA(fe)){
WRITE_REG(REG_T1RBOCC, BIT_T1RBOCC_RBD0 | BIT_T1RBOCC_RBF1 | BIT_T1RBOCC_RBF0);
WRITE_REG(REG_T1RIBCC, BIT_T1RIBCC_RUP2 | BIT_T1RIBCC_RDN1);
WRITE_REG(REG_T1RUPCD1, 0x80);
WRITE_REG(REG_T1RDNCD1, 0x80);
}
/* T1/J1 or E1 */
if (IS_T1_FEMEDIA(fe)){
WRITE_REG(REG_LTRCR, BIT_LTRCR_T1J1E1S);
}else{
/* E1 | G.775 LOS */
WRITE_REG(REG_LTRCR, 0x00);
}
value = 0x00;
switch(WAN_TE1_LBO(fe)) {
case WAN_T1_LBO_0_DB:
value = 0x00;
break;
case WAN_T1_LBO_75_DB:
value = BIT_LTITSR_L2 | BIT_LTITSR_L0;
break;
case WAN_T1_LBO_15_DB:
value = BIT_LTITSR_L2 | BIT_LTITSR_L1;
break;
case WAN_T1_LBO_225_DB:
value = BIT_LTITSR_L2 | BIT_LTITSR_L1 | BIT_LTITSR_L0;
break;
case WAN_T1_0_133: case WAN_T1_0_110:
value = 0x00;
break;
case WAN_T1_133_266: case WAN_T1_110_220:
value = BIT_LTITSR_L0;
break;
case WAN_T1_266_399: case WAN_T1_220_330:
value = BIT_LTITSR_L1;
break;
case WAN_T1_399_533: case WAN_T1_330_440:
value = BIT_LTITSR_L1 | BIT_LTITSR_L0;
break;
case WAN_T1_533_655: case WAN_T1_440_550: case WAN_T1_550_660:
value = BIT_LTITSR_L2;
break;
case WAN_E1_120:
value = BIT_LTITSR_L0;
break;
case WAN_E1_75:
value = 0x00;
break;
default:
if (IS_E1_FEMEDIA(fe)){
value = BIT_LTITSR_L0;
}
break;
}
if (IS_T1_FEMEDIA(fe)){
WRITE_REG(REG_LTITSR, value | BIT_LTITSR_TIMPL0);
}else if (IS_E1_FEMEDIA(fe)){
if (WAN_TE1_LBO(fe) == WAN_E1_120){
value |= (BIT_LTITSR_TIMPL1 | BIT_LTITSR_TIMPL0);
}
WRITE_REG(REG_LTITSR, value);
}else if (IS_J1_FEMEDIA(fe)){
WRITE_REG(REG_LTITSR,
value | BIT_LTITSR_TIMPL0);
}
value = 0x00;
if (WAN_TE1_HI_MODE(fe)){
value |= BIT_LRISMR_RMONEN;
switch(fe->fe_cfg.cfg.te_cfg.rx_slevel){
case WAN_TE1_RX_SLEVEL_30_DB:
break;
case WAN_TE1_RX_SLEVEL_225_DB:
value |= BIT_LRISMR_RSMS0;
break;
case WAN_TE1_RX_SLEVEL_175_DB:
value |= BIT_LRISMR_RSMS1;
break;
case WAN_TE1_RX_SLEVEL_12_DB:
value |= (BIT_LRISMR_RSMS1 | BIT_LRISMR_RSMS0);
break;
default: /* set default value */
fe->fe_cfg.cfg.te_cfg.rx_slevel = WAN_TE1_RX_SLEVEL_30_DB;
break;
}
DEBUG_EVENT(
"%s: Rx Sensitivity Gain %s%s (High Impedence mode).\n",
fe->name,
WAN_TE1_RX_SLEVEL_DECODE(fe->fe_cfg.cfg.te_cfg.rx_slevel),
(fe->fe_cfg.cfg.te_cfg.rx_slevel==WAN_TE1_RX_SLEVEL_30_DB)?
" (default)":"");
}else{
switch(fe->fe_cfg.cfg.te_cfg.rx_slevel){
case WAN_TE1_RX_SLEVEL_12_DB:
break;
case WAN_TE1_RX_SLEVEL_18_DB:
value |= BIT_LRISMR_RSMS0;
break;
case WAN_TE1_RX_SLEVEL_30_DB:
value |= BIT_LRISMR_RSMS1;
break;
case WAN_TE1_RX_SLEVEL_36_DB:
case WAN_TE1_RX_SLEVEL_43_DB:
default: /* set default value */
value |= (BIT_LRISMR_RSMS1 | BIT_LRISMR_RSMS0);
break;
}
DEBUG_EVENT("%s: Rx Sensitivity Gain %s%s.\n",
fe->name,
WAN_TE1_RX_SLEVEL_DECODE(fe->fe_cfg.cfg.te_cfg.rx_slevel),
((IS_T1_FEMEDIA(fe) && (fe->fe_cfg.cfg.te_cfg.rx_slevel==WAN_TE1_RX_SLEVEL_36_DB)) ||
(IS_E1_FEMEDIA(fe) && (fe->fe_cfg.cfg.te_cfg.rx_slevel==WAN_TE1_RX_SLEVEL_43_DB))) ?
" (default)": "");
}
if (IS_T1_FEMEDIA(fe)){
value |= BIT_LRISMR_RIMPM0;
}else{
//value |= BIT_LRISMR_RIMPOFF;
if (WAN_TE1_LBO(fe) == WAN_E1_120){
value |= BIT_LRISMR_RIMPM1 | BIT_LRISMR_RIMPM0;
}
}
WRITE_REG(REG_LRISMR, value);
if (IS_E1_FEMEDIA(fe) && WAN_TE1_LBO(fe) == WAN_E1_120){
/* Feb 7, 2008
** Adjust DAC gain (-4.88%) */
WRITE_REG(REG_LTXLAE, 0x09);
}
/* Additional front-end settings */
value = READ_REG(REG_ERCNT);
if (WAN_FE_LCODE(fe) == WAN_LCODE_AMI){
value &= ~BIT_ERCNT_LCVCRF;
}else{
value |= BIT_ERCNT_LCVCRF;
}
value |= BIT_ERCNT_EAMS; /* manual mode select */
WRITE_REG(REG_ERCNT, value);
#if 1
if (WAN_TE1_ACTIVE_CH(fe) != ENABLE_ALL_CHANNELS){
unsigned long active_ch = WAN_TE1_ACTIVE_CH(fe);
int channel_range = (IS_T1_FEMEDIA(fe)) ?
NUM_OF_T1_CHANNELS : NUM_OF_E1_TIMESLOTS;
unsigned char rescr, tescr, gfcr;
int i = 0;
DEBUG_EVENT("%s: %s:%d: Disable channels: ",
fe->name,
FE_MEDIA_DECODE(fe), WAN_FE_LINENO(fe)+1);
for(i = 1; i <= channel_range; i++){
if (!(active_ch & (1 << (i-1)))){
_DEBUG_EVENT("%d ", i);
sdla_ds_te1_TxChanCtrl(fe, i, 0);
sdla_ds_te1_RxChanCtrl(fe, i, 0);
}
}
_DEBUG_EVENT("\n");
gfcr = READ_REG(REG_GFCR);
WRITE_REG(REG_GFCR, gfcr | BIT_GFCR_TCBCS | BIT_GFCR_RCBCS);
rescr = READ_REG(REG_RESCR);
WRITE_REG(REG_RESCR, rescr | BIT_RESCR_RGCLKEN);
tescr = READ_REG(REG_TESCR);
WRITE_REG(REG_TESCR, tescr | BIT_TESCR_TGPCKEN);
}
#endif
if (WAN_FE_FRAME(fe) != WAN_FR_UNFRAMED){
/* Set INIT_DONE (for not unframed mode) */
value = READ_REG(REG_RMMR);
WRITE_REG(REG_RMMR, value | BIT_RMMR_INIT_DONE);
value = READ_REG(REG_TMMR);
WRITE_REG(REG_TMMR, value | BIT_TMMR_INIT_DONE);
}
/* Turn on LIU output */
if (IS_FE_TXTRISTATE(fe)){
DEBUG_EVENT("%s: Disable TX (tri-state mode)\n",
fe->name);
}else{
/* Sep 17, 2009 - Auto AIS transmition (experimental) */
WRITE_REG(REG_LMCR, BIT_LMCR_ATAIS | BIT_LMCR_TE);
}
/* INIT RBS bits to 1 */
sdla_ds_te1_rbs_init(fe);
return 0;
}
#if 0
/*
******************************************************************************
* sdla_ds_te1_chip_config_verify()
*
* Description: Configure Sangoma 8 ports T1/E1 board
* Arguments:
* Returns: WANTRUE - TE1 configred successfully, otherwise WAN_FALSE.
******************************************************************************
*/
static int sdla_ds_te1_chip_config_verify(sdla_fe_t *fe)
{
int e1_mode = 0;
u_int8_t rmmr, tmmr, value = 0x00;
WAN_ASSERT(fe->write_fe_reg == NULL);
WAN_ASSERT(fe->read_fe_reg == NULL);
rmmr = READ_REG(REG_RMMR);
DEBUG_EVENT("%s: RX: %s mode\n",
fe->name, (rmmr & BIT_RMMR_T1E1) ? "E1" : "T1");
e1_mode = (value & BIT_RMMR_T1E1) ? 1 : 0;
tmmr = READ_REG(REG_TMMR);
DEBUG_EVENT("%s: TX: %s mode\n",
fe->name, (tmmr & BIT_TMMR_T1E1) ? "E1" : "T1");
if ((rmmr & BIT_RMMR_T1E1) && (tmmr & BIT_RMMR_T1E1)){
e1_mode = 1;
} else if ((rmmr & BIT_RMMR_T1E1) || (tmmr & BIT_RMMR_T1E1)){
DEBUG_EVENT(
"%s: ERROR: RX/TX has different mode configuration (%02X:%02X)!\n",
fe->name, rmmr, tmmr);
return -EINVAL;
}
if (e1_mode){
value = READ_REG(REG_RCR1);
DEBUG_EVENT("%s: RX Ctrl Reg: %s %s %s\n",
fe->name,
(value & BIT_RCR1_E1_RCRC4) ? "CRC4" : "NCRC4",
(value & BIT_RCR1_E1_RHDB3) ? "HDB3": "AMI",
(value & BIT_RCR1_E1_RSIGM) ? "CCS" : "CAS");
value = READ_REG(REG_TCR1);
DEBUG_EVENT("%s: TX Ctrl Reg: %s %s %s\n",
fe->name,
(value & BIT_TCR1_E1_TCRC4) ? "CRC4" : "NCRC4",
(value & BIT_TCR1_E1_THDB3) ? "HDB3": "AMI",
(value & BIT_TCR1_E1_T16S) ? "CAS" : "CCS");
}else{
value = READ_REG(REG_RCR1);
DEBUG_EVENT("%s: RX Ctrl Reg: %s %s\n",
fe->name,
(value & BIT_RCR1_T1_RFM) ? "D4" : "ESF",
(value & BIT_RCR1_T1_RB8ZS) ? "B8ZS": "AMI");
value = READ_REG(REG_TCR1);
DEBUG_EVENT("%s: TX Ctrl Reg: %s\n",
fe->name,
(value & BIT_TCR1_T1_TB8ZS) ? "B8ZS": "AMI");
value = READ_REG(REG_TCR3);
DEBUG_EVENT("%s: TX Ctrl Reg: %s\n",
fe->name,
(value & BIT_TCR3_TFM) ? "D4" : "ESF");
}
return 0;
}
#endif
/*
******************************************************************************
* sdla_ds_te1_config()
*
* Description: Configure Sangoma 8 ports T1/E1 board
* Arguments:
* Returns: WANTRUE - TE1 configred successfully, otherwise WAN_FALSE.
******************************************************************************
*/
static int sdla_ds_te1_config(void* pfe)
{
sdla_fe_t *fe = (sdla_fe_t*)pfe;
int err = 0;
WAN_ASSERT(fe->write_fe_reg == NULL);
WAN_ASSERT(fe->read_fe_reg == NULL);
/* Revision/Chip ID (Reg. 0x0D) */
if (sdla_ds_te1_device_id(fe)) return -EINVAL;
switch(fe->fe_chip_id){
case DEVICE_ID_DS26528:
if ((int)WAN_FE_LINENO(fe) < 0 || WAN_FE_LINENO(fe) > 8){
DEBUG_EVENT(
"%s: TE Config: Invalid Port selected %d (Min=1 Max=8)\n",
fe->name,
WAN_FE_LINENO(fe)+1);
return -EINVAL;
}
break;
case DEVICE_ID_DS26524:
if ((int)WAN_FE_LINENO(fe) < 0 || WAN_FE_LINENO(fe) > 4){
DEBUG_EVENT(
"%s: TE Config: Invalid Port selected %d (Min=1 Max=4)\n",
fe->name,
WAN_FE_LINENO(fe)+1);
return -EINVAL;
}
break;
case DEVICE_ID_DS26521:
case DEVICE_ID_DS26522:
if ((int)WAN_FE_LINENO(fe) < 0 || WAN_FE_LINENO(fe) > 1){
DEBUG_EVENT(
"%s: TE Config: Invalid Port selected %d (Min=1 Max=2)\n",
fe->name,
WAN_FE_LINENO(fe)+1);
return -EINVAL;
}
break;
}
if (IS_T1_FEMEDIA(fe) || IS_J1_FEMEDIA(fe)){
err = sdla_ds_t1_cfg_verify(fe);
}else if (IS_E1_FEMEDIA(fe)){
err = sdla_ds_e1_cfg_verify(fe);
}else{
DEBUG_EVENT("%s: Error: Invalid FE Media type (%X)\n",
fe->name,
WAN_FE_MEDIA(fe));
err =-EINVAL;
}
if (err) return -EINVAL;
DEBUG_EVENT("%s: Configuring DS %s %s FE\n",
fe->name,
DECODE_CHIPID(fe->fe_chip_id),
FE_MEDIA_DECODE(fe));
DEBUG_EVENT("%s: Port %d,%s,%s,%s\n",
fe->name,
WAN_FE_LINENO(fe)+1,
FE_LCODE_DECODE(fe),
FE_FRAME_DECODE(fe),
TE_LBO_DECODE(fe));
DEBUG_EVENT("%s: Clk %s:%d, Channels: %X\n",
fe->name,
TE_CLK_DECODE(fe),
WAN_TE1_REFCLK(fe),
WAN_TE1_ACTIVE_CH(fe));
if (IS_E1_FEMEDIA(fe)){
DEBUG_EVENT("%s: Sig Mode %s\n",
fe->name,
WAN_TE1_SIG_DECODE(fe));
}
if (fe->fe_cfg.poll_mode == WANOPT_YES){
sdla_t *card = (sdla_t*)fe->card;
DEBUG_EVENT("%s: FE Poll driven\n",
fe->name);
card->fe_no_intr = 1; /* disable global front interrupt */
}
if (fe->fe_cfg.cfg.te_cfg.ignore_yel_alarm == WANOPT_YES){
DEBUG_EVENT("%s: YEL alarm ignored\n",
fe->name);
}
if (sdla_ds_te1_chip_config(fe)){
return -EINVAL;
}
fe->te_param.max_channels =
(IS_E1_FEMEDIA(fe)) ? NUM_OF_E1_TIMESLOTS: NUM_OF_T1_CHANNELS;
sdla_ds_te1_flush_pmon(fe);
fe->swirq = wan_malloc(WAN_TE1_SWIRQ_MAX*sizeof(sdla_fe_swirq_t));
if (fe->swirq == NULL){
DEBUG_EVENT("%s: Failed to allocate memory (%s:%d)!\n",
fe->name, __FUNCTION__, __LINE__);
return -EINVAL;
}
memset(fe->swirq, 0, WAN_TE1_SWIRQ_MAX*sizeof(sdla_fe_swirq_t));
wan_set_bit(TE_CONFIGURED,(void*)&fe->te_param.critical);
#if 0
/* FIXME: Enable all interrupt only when link is connected (event global) */
/* Enable interrupts */
sdla_ds_te1_intr_ctrl(fe, 0, WAN_TE_INTR_GLOBAL, WAN_FE_INTR_ENABLE, 0x00);
#endif
return 0;
}
/*
******************************************************************************
* sdla_ds_te1_post_init()
*
* Description: T1/E1 post init.
* Arguments:
* Returns:
******************************************************************************
*/
static int sdla_ds_te1_post_init(void* pfe)
{
sdla_fe_t *fe = (sdla_fe_t*)pfe;
/* Initialize and start T1/E1 timer */
wan_set_bit(TE_TIMER_KILL,(void*)&fe->te_param.critical);
wan_init_timer(&fe->timer, sdla_ds_te1_timer, (wan_timer_arg_t)fe);
/* Initialize T1/E1 timer */
wan_clear_bit(TE_TIMER_KILL,(void*)&fe->te_param.critical);
/* Start T1/E1 timer */
sdla_ds_te1_swirq_trigger(
fe,
WAN_TE1_SWIRQ_TYPE_LINK,
WAN_TE1_SWIRQ_SUBTYPE_LINKDOWN,
POLLING_TE1_TIMER);
sdla_ds_te1_add_timer(fe, POLLING_TE1_TIMER);
return 0;
}
/*
******************************************************************************
* sdla_ds_te1_pre_release()
*
* Description: T1/E1 pre release function (not locked routines)
* Arguments:
* Returns:
******************************************************************************
*/
static int sdla_ds_te1_pre_release(void* pfe)
{
sdla_fe_t *fe = (sdla_fe_t*)pfe;
sdla_fe_timer_event_t *fe_event = NULL;
wan_smp_flag_t smp_flags;
int empty = 0;
/* Kill TE timer poll command */
wan_set_bit(TE_TIMER_KILL,(void*)&fe->te_param.critical);
if (wan_test_bit(TE_TIMER_RUNNING,(void*)&fe->te_param.critical)){
wan_del_timer(&fe->timer);
}
wan_clear_bit(TE_TIMER_RUNNING,(void*)&fe->te_param.critical);
do{
wan_spin_lock_irq(&fe->lockirq,&smp_flags);
if (!WAN_LIST_EMPTY(&fe->event)){
fe_event = WAN_LIST_FIRST(&fe->event);
WAN_LIST_REMOVE(fe_event, next);
}else{
empty = 1;
}
wan_spin_unlock_irq(&fe->lockirq,&smp_flags);
/* Free should be called not from spin_lock_irq (windows) !!!! */
if (fe_event) wan_free(fe_event);
fe_event = NULL;
}while(!empty);
if (fe->swirq){
wan_free(fe->swirq);
fe->swirq = NULL;
}
return 0;
}
/*
******************************************************************************
* sdla_ds_te1_unconfig()
*
* Description: T1/E1 unconfig.
* Arguments:
* Returns:
******************************************************************************
*/
static int sdla_ds_te1_unconfig(void* pfe)
{
sdla_fe_t *fe = (sdla_fe_t*)pfe;
/* Verify if FE timer is stopped */
if (!wan_test_bit(TE_TIMER_KILL,(void*)&fe->te_param.critical)){
DEBUG_EVENT("%s: %s(): Front-End timer is not stopped!\n",
fe->name, __FUNCTION__);
return -EINVAL;
}
DEBUG_EVENT("%s: %s Front End unconfigation!\n",
fe->name, FE_MEDIA_DECODE(fe));
/* FIXME: Alex to disable interrupts here */
sdla_ds_te1_disable_irq(fe);
/* Set Rx Framer soft reset */
WRITE_REG(REG_RMMR, BIT_RMMR_SFTRST);
/* Set Tx Framer soft reset */
WRITE_REG(REG_TMMR, BIT_RMMR_SFTRST);
/* Clear configuration flag */
wan_clear_bit(TE_CONFIGURED,(void*)&fe->te_param.critical);
//sdla_ds_te1_reset(fe, WAN_FE_LINENO(fe)+1, 1);
//if (fe->fe_chip_id == DEVICE_ID_DS26521/* && fe->fe_cfg.line_no == 1*/){
// sdla_ds_te1_global_unconfig(fe);
//}
return 0;
}
/*
******************************************************************************
* sdla_ds_te1_disable_irq()
*
* Description: T1/E1 unconfig.
* Arguments:
* Returns:
******************************************************************************
*/
static int sdla_ds_te1_disable_irq(void* pfe)
{
sdla_fe_t *fe = (sdla_fe_t*)pfe;
if (fe->fe_cfg.poll_mode == WANOPT_NO){
/* Disable all interrupts */
sdla_ds_te1_intr_ctrl(
fe, 0,
(WAN_TE_INTR_GLOBAL|WAN_TE_INTR_BASIC|WAN_TE_INTR_PMON),
WAN_FE_INTR_MASK, 0x00);
}
return 0;
}
/*
******************************************************************************
* sdla_ds_te1_reconfig()
*
* Description: T1/E1 post configuration.
* Arguments:
* Returns:
******************************************************************************
*/
static int sdla_ds_te1_reconfig(sdla_fe_t* fe)
{
if (IS_E1_FEMEDIA(fe)){
sdla_ds_e1_set_sig_mode(fe, 1);
}
return 0;
}
static int
sdla_ds_te1_sigctrl(sdla_fe_t *fe, int sig_mode, unsigned long ch_map, int mode)
{
sdla_fe_timer_event_t event;
int err;
event.type = (mode == WAN_ENABLE) ?
TE_RBS_ENABLE : TE_RBS_DISABLE;
event.delay = POLLING_TE1_TIMER;
event.te_event.ch_map = ch_map;
err = sdla_ds_te1_add_event(fe, &event);
if (err){
DEBUG_EVENT("%s: Failed to add new fe event %02X ch_map=%08lX!\n",
fe->name,
event.type, event.te_event.ch_map);
return -EINVAL;
}
return 0;
}
/******************************************************************************
** sdla_ds_t1_is_alarm()
**
** Description: Verify T1 status.
** Arguments:
** Returns: 1 - the port is connected
** 0 - the port is disconnected
******************************************************************************/
static u_int32_t sdla_ds_t1_is_alarm(sdla_fe_t *fe, u_int32_t alarms)
{
u_int32_t alarm_mask = WAN_T1_FRAMED_ALARMS;
/* Alex Feb 27, 2008
** Special case for customer that uses
** YEL alarm for protocol control */
if (fe->fe_cfg.cfg.te_cfg.ignore_yel_alarm == WANOPT_NO){
alarm_mask |= WAN_TE_BIT_RAI_ALARM;
}
return (alarms & alarm_mask);
}
/******************************************************************************
** sdla_ds_e1_is_alarm()
**
** Description: Verify E1 status.
** Arguments:
** Returns: 1 - the port is connected
** 0 - the port is disconnected
******************************************************************************/
static u_int32_t sdla_ds_e1_is_alarm(sdla_fe_t *fe, u_int32_t alarms)
{
u_int32_t alarm_mask = 0x00;
if (WAN_FE_FRAME(fe) == WAN_FR_UNFRAMED){
alarm_mask = WAN_TE1_UNFRAMED_ALARMS;
if (!fe->te_param.lb_mode_map){
alarm_mask |= ( WAN_TE_BIT_ALARM_LIU_OC |
WAN_TE_BIT_ALARM_LIU_SC |
WAN_TE_BIT_ALARM_LIU_LOS);
}
}else{
alarm_mask = WAN_E1_FRAMED_ALARMS;
}
/* Alex Feb 27, 2008
** Special case for customer that uses
** YEL alarm for protocol control */
if (fe->fe_cfg.cfg.te_cfg.ignore_yel_alarm == WANOPT_NO){
alarm_mask |= WAN_TE_BIT_RAI_ALARM;
}
return (alarms & alarm_mask);
}
/******************************************************************************
** sdla_ds_te1_set_status()
**
** Description: Set T1/E1 status. Enable OOF and LCV interrupt (if status
** changed to disconnected.
** Arguments:
** Returns:
******************************************************************************/
static int sdla_ds_te1_set_status(sdla_fe_t* fe, u_int32_t alarms)
{
sdla_t *card = (sdla_t*)fe->card;
unsigned char new_fe_status = fe->fe_status;
u_int32_t valid_rx_alarms = 0x00;
if (IS_T1_FEMEDIA(fe)){
valid_rx_alarms = sdla_ds_t1_is_alarm(fe, alarms);
}else if (IS_E1_FEMEDIA(fe)){
valid_rx_alarms = sdla_ds_e1_is_alarm(fe, alarms);
}
if (valid_rx_alarms){
if (fe->fe_status != FE_DISCONNECTED){
new_fe_status = FE_DISCONNECTED;
}
}else{
if (fe->fe_status != FE_CONNECTED){
new_fe_status = FE_CONNECTED;
}
}
if (fe->fe_status == new_fe_status){
if (fe->te_param.tx_yel_alarm && valid_rx_alarms == WAN_TE_BIT_RAI_ALARM){
sdla_ds_te1_clear_alarms(fe, WAN_TE_BIT_YEL_ALARM);
}
fe->te_param.status_cnt = 0;
DEBUG_TE1("%s: %s %s...%d\n",
fe->name,
FE_MEDIA_DECODE(fe),
WAN_FE_STATUS_DECODE(fe),
fe->te_param.status_cnt);
return 0;
}
if (new_fe_status == FE_CONNECTED){
if (fe->te_param.status_cnt > WAN_TE1_STATUS_THRESHOLD){
if (fe->te_param.tx_yel_alarm){
sdla_ds_te1_clear_alarms(fe, WAN_TE_BIT_ALARM_YEL);
}
DEBUG_EVENT("%s: %s connected!\n",
fe->name,
FE_MEDIA_DECODE(fe));
fe->fe_status = FE_CONNECTED;
if (card->wandev.te_report_alarms){
card->wandev.te_report_alarms(
card,
fe->fe_alarm);
}
}else{
if (!fe->te_param.status_cnt){
DEBUG_TE1("%s: %s connecting...\n",
fe->name,
FE_MEDIA_DECODE(fe));
}
fe->te_param.status_cnt ++;
fe->fe_status = FE_DISCONNECTED;
DEBUG_TE1("%s: %s connecting...%d\n",
fe->name,
FE_MEDIA_DECODE(fe),
fe->te_param.status_cnt);
}
}else{
DEBUG_EVENT("%s: %s disconnected!\n",
fe->name,
FE_MEDIA_DECODE(fe));
fe->fe_status = FE_DISCONNECTED;
/* Special case, if remote alarms is ONLY RAI, then do not transmit yellow */
if (!fe->te_param.tx_yel_alarm && !(valid_rx_alarms == WAN_TE_BIT_RAI_ALARM)){
sdla_ds_te1_set_alarms(fe, WAN_TE_BIT_ALARM_YEL);
}
/* Special case, loopback if only valid alarm is RAI and we already transmitted yellow,
then we must clear yellow */
if (fe->te_param.tx_yel_alarm && valid_rx_alarms == WAN_TE_BIT_RAI_ALARM){
sdla_ds_te1_clear_alarms(fe, WAN_TE_BIT_YEL_ALARM);
}
fe->te_param.status_cnt = 0;
if (card->wandev.te_report_alarms){
card->wandev.te_report_alarms(card, fe->fe_alarm);
}
}
return 1;
}
/*
*******************************************************************************
** sdla_te_alarm_print()
**
** Description:
** Arguments:
** Returns:
*/
static int sdla_ds_te1_print_alarms(sdla_fe_t* fe, unsigned int alarms)
{
if (!alarms){
DEBUG_EVENT("%s: %s Alarms status: No alarms detected!\n",
fe->name,
FE_MEDIA_DECODE(fe));
return 0;
}
DEBUG_EVENT("%s: %s Framer Alarms status (%08X):\n",
fe->name,
FE_MEDIA_DECODE(fe),
alarms & WAN_TE_ALARM_FRAMER_MASK);
if (alarms & WAN_TE_BIT_ALARM_RAI){
DEBUG_EVENT("%s: RAI : ON\n", fe->name);
}
if (alarms & WAN_TE_BIT_ALARM_LOS){
DEBUG_EVENT("%s: LOS : ON\n", fe->name);
}
if (alarms & WAN_TE_BIT_ALARM_OOF){
DEBUG_EVENT("%s: OOF : ON\n", fe->name);
}
if (alarms & WAN_TE_BIT_ALARM_RED){
DEBUG_EVENT("%s: RED : ON\n", fe->name);
}
DEBUG_EVENT("%s: %s LIU Alarms status (%08X):\n",
fe->name,
FE_MEDIA_DECODE(fe),
alarms & WAN_TE_ALARM_LIU_MASK);
if (alarms & WAN_TE_BIT_ALARM_LIU_OC){
DEBUG_EVENT("%s: Open Circuit is detected!\n",
fe->name);
}
if (alarms & WAN_TE_BIT_ALARM_LIU_SC){
DEBUG_EVENT("%s: Short Circuit is detected!\n",
fe->name);
}
if (alarms & WAN_TE_BIT_ALARM_LIU_LOS){
DEBUG_EVENT("%s: Lost of Signal is detected!\n",
fe->name);
}
return 0;
}
/******************************************************************************
** sdla_te_read_alarms()
**
** Description:
** Arguments:
** Returns:
******************************************************************************/
static u_int32_t sdla_ds_te1_read_frame_alarms(sdla_fe_t *fe)
{
u_int32_t alarm = fe->fe_alarm;
unsigned char rrts1 = READ_REG(REG_RRTS1);
alarm &= WAN_TE_ALARM_FRAMER_MASK;
DEBUG_TE1("%s: Reading %s Framer status (Old:%08X,%02X)\n",
fe->name, FE_MEDIA_DECODE(fe),
rrts1, alarm);
/* Framer alarms */
//if (WAN_FE_FRAME(fe) != WAN_FR_UNFRAMED){
if (rrts1 & BIT_RRTS1_RRAI){
if (!(alarm & WAN_TE_BIT_ALARM_RAI)){
DEBUG_EVENT("%s: RAI : ON\n",
fe->name);
}
alarm |= WAN_TE_BIT_ALARM_RAI;
}else{
if (alarm & WAN_TE_BIT_ALARM_RAI){
DEBUG_EVENT("%s: RAI : OFF\n",
fe->name);
}
alarm &= ~WAN_TE_BIT_ALARM_RAI;
}
//}
if (rrts1 & BIT_RRTS1_RAIS){
if (!IS_TE_ALARM_AIS(alarm)){
sdla_ds_te1_swirq_trigger(
fe,
WAN_TE1_SWIRQ_TYPE_ALARM_AIS,
WAN_TE1_SWIRQ_SUBTYPE_ALARM_ON,
WAN_T1_ALARM_THRESHOLD_AIS_ON);
}
}else{
if (IS_TE_ALARM_AIS(alarm)){
sdla_ds_te1_swirq_trigger(
fe,
WAN_TE1_SWIRQ_TYPE_ALARM_AIS,
WAN_TE1_SWIRQ_SUBTYPE_ALARM_OFF,
WAN_T1_ALARM_THRESHOLD_AIS_OFF);
}
}
if (rrts1 & BIT_RRTS1_RLOS){
if (!IS_TE_ALARM_LOS(alarm)){
sdla_ds_te1_swirq_trigger(
fe,
WAN_TE1_SWIRQ_TYPE_ALARM_LOS,
WAN_TE1_SWIRQ_SUBTYPE_ALARM_ON,
WAN_T1_ALARM_THRESHOLD_LOS_ON);
}
}else{
if (IS_TE_ALARM_LOS(alarm)){
sdla_ds_te1_swirq_trigger(
fe,
WAN_TE1_SWIRQ_TYPE_ALARM_LOS,
WAN_TE1_SWIRQ_SUBTYPE_ALARM_OFF,
WAN_T1_ALARM_THRESHOLD_LOS_OFF);
}
}
if (WAN_FE_FRAME(fe) != WAN_FR_UNFRAMED){
if (rrts1 & BIT_RRTS1_RLOF){
if (!IS_TE_ALARM_LOF(alarm)){
sdla_ds_te1_swirq_trigger(
fe,
WAN_TE1_SWIRQ_TYPE_ALARM_LOF,
WAN_TE1_SWIRQ_SUBTYPE_ALARM_ON,
WAN_T1_ALARM_THRESHOLD_LOF_ON);
}
}else{
if (IS_TE_ALARM_LOF(alarm)){
sdla_ds_te1_swirq_trigger(
fe,
WAN_TE1_SWIRQ_TYPE_ALARM_LOF,
WAN_TE1_SWIRQ_SUBTYPE_ALARM_OFF,
WAN_T1_ALARM_THRESHOLD_LOF_OFF);
}
}
}
/* Aug 30, 2006
** Red alarm is either LOS or OOF alarms */
if (IS_TE_ALARM_LOF(alarm) ||
IS_TE_ALARM_LOS(alarm)){
if (!IS_TE_ALARM_RED(alarm)){
DEBUG_EVENT("%s: RED : ON\n",
fe->name);
}
alarm |= WAN_TE_BIT_ALARM_RED;
}else{
if (IS_TE_ALARM_RED(alarm)){
DEBUG_EVENT("%s: RED : OFF\n",
fe->name);
}
alarm &= ~WAN_TE_BIT_ALARM_RED;
}
return alarm;
}
static unsigned int sdla_ds_te1_read_liu_alarms(sdla_fe_t *fe)
{
unsigned int alarm = fe->fe_alarm;
unsigned char lrsr = READ_REG(REG_LRSR);
alarm &= WAN_TE_ALARM_LIU_MASK;
DEBUG_TE1("%s: Reading %s LIU status (Old:%08X,%02X)\n",
fe->name, FE_MEDIA_DECODE(fe),
lrsr, alarm);
/* LIU alarms */
if (lrsr & BIT_LRSR_OCS){
if (!(alarm & WAN_TE_BIT_ALARM_LIU_OC)){
DEBUG_EVENT("%s: Open Circuit is detected!\n",
fe->name);
}
alarm |= WAN_TE_BIT_ALARM_LIU_OC;
}else{
if (alarm & WAN_TE_BIT_ALARM_LIU_OC){
DEBUG_EVENT("%s: Open Circuit is cleared!\n",
fe->name);
}
alarm &= ~WAN_TE_BIT_ALARM_LIU_OC;
}
if (lrsr & BIT_LRSR_SCS){
if (!(alarm & WAN_TE_BIT_ALARM_LIU_SC)){
DEBUG_EVENT("%s: Short Circuit is detected!(%i)\n",
fe->name, __LINE__);
}
alarm |= WAN_TE_BIT_ALARM_LIU_SC;
}else{
if (alarm & WAN_TE_BIT_ALARM_LIU_SC){
DEBUG_EVENT("%s: Short Circuit is cleared!(%i)\n",
fe->name, __LINE__);
}
alarm &= ~WAN_TE_BIT_ALARM_LIU_SC;
}
if (lrsr & BIT_LRSR_LOSS){
if (!(alarm & WAN_TE_BIT_ALARM_LIU_LOS)){
DEBUG_EVENT("%s: Lost of Signal is detected!\n",
fe->name);
}
alarm |= WAN_TE_BIT_ALARM_LIU_LOS;
}else{
if (alarm & WAN_TE_BIT_ALARM_LIU_LOS){
DEBUG_EVENT("%s: Lost of Signal is cleared!\n",
fe->name);
}
alarm &= ~WAN_TE_BIT_ALARM_LIU_LOS;
}
return alarm;
}
static u_int32_t sdla_ds_te1_read_alarms(sdla_fe_t *fe, int action)
{
u_int32_t alarm = fe->fe_alarm;
if (IS_FE_ALARM_READ(action)){
alarm = sdla_ds_te1_read_frame_alarms(fe);
alarm |= sdla_ds_te1_read_liu_alarms(fe);
}
if (IS_FE_ALARM_PRINT(action)){
sdla_ds_te1_print_alarms(fe, alarm);
}
if (IS_FE_ALARM_UPDATE(action)){
fe->fe_alarm = alarm;
}
return fe->fe_alarm;
}
/******************************************************************************
** sdla_ds_te1_update_alarm()
**
** Description:
** Arguments:
** Returns:
******************************************************************************/
static int
sdla_ds_te1_update_alarms(sdla_fe_t *fe, u_int32_t alarms)
{
if (!IS_TE_ALARM_AIS(fe->fe_alarm)){
if (IS_TE_ALARM_AIS(alarms)){
DEBUG_EVENT("%s: AIS : ON\n",
fe->name);
fe->fe_alarm |= WAN_TE_BIT_ALARM_AIS;
}
}else{
if (!IS_TE_ALARM_AIS(alarms)){
DEBUG_EVENT("%s: AIS : OFF\n",
fe->name);
fe->fe_alarm &= ~WAN_TE_BIT_ALARM_AIS;
}
}
if (!IS_TE_ALARM_LOF(fe->fe_alarm)){
if (IS_TE_ALARM_LOF(alarms)){
DEBUG_EVENT("%s: LOF : ON\n",
fe->name);
fe->fe_alarm |= WAN_TE_BIT_ALARM_LOF;
}
}else{
if (!IS_TE_ALARM_LOF(alarms)){
DEBUG_EVENT("%s: LOF : OFF\n",
fe->name);
fe->fe_alarm &= ~WAN_TE_BIT_ALARM_LOF;
}
}
if (!IS_TE_ALARM_LOS(fe->fe_alarm)){
if (IS_TE_ALARM_LOS(alarms)){
DEBUG_EVENT("%s: LOS : ON\n",
fe->name);
fe->fe_alarm |= WAN_TE_BIT_ALARM_LOS;
}
}else{
if (!IS_TE_ALARM_LOS(alarms)){
DEBUG_EVENT("%s: LOS : OFF\n",
fe->name);
fe->fe_alarm &= ~WAN_TE_BIT_ALARM_LOS;
}
}
if (IS_T1_FEMEDIA(fe)){
if (IS_TE_ALARM_LOF(fe->fe_alarm) ||
IS_TE_ALARM_LOS(fe->fe_alarm)){
if (!IS_TE_ALARM_RED(fe->fe_alarm)){
DEBUG_EVENT("%s: RED : ON\n",
fe->name);
}
fe->fe_alarm |= WAN_TE_BIT_ALARM_RED;
}else{
if (IS_TE_ALARM_RED(fe->fe_alarm)){
DEBUG_EVENT("%s: RED : OFF\n",
fe->name);
}
fe->fe_alarm &= ~WAN_TE_BIT_ALARM_RED;
}
}
return 0;
}
#define WAN_TE_CRIT_ALARM_TIMEOUT 30 /* 30 sec */
static int sdla_ds_te1_read_crit_alarms(sdla_fe_t *fe)
{
u_int32_t liu_alarms = 0x00;
liu_alarms = sdla_ds_te1_read_liu_alarms(fe);
if (liu_alarms & WAN_TE_BIT_ALARM_LIU_SC){
fe->te_param.crit_alarm_start = SYSTEM_TICKS;
}else{
if (WAN_STIMEOUT(fe->te_param.crit_alarm_start, WAN_TE_CRIT_ALARM_TIMEOUT)){
/* The link was stable for 30 sec, let try to go back */
return 0;
}
}
/* we are still in critical alarm state */
return 1;
}
/******************************************************************************
** sdla_ds_te1_set_alarms()
**
** Description:
** Arguments:
** Returns:
*/
static int sdla_ds_te1_set_alarms(sdla_fe_t* fe, u_int32_t alarms)
{
u8 value;
/* NC: Always set yellow alarm no need to check whether
* yellow alarm is ignored */
if (alarms & WAN_TE_BIT_ALARM_YEL){
if (IS_T1_FEMEDIA(fe)){
value = READ_REG(REG_TCR1);
if (!(value & BIT_TCR1_T1_TRAI)){
DEBUG_EVENT("%s: Enable transmit RAI alarm\n",
fe->name);
WRITE_REG(REG_TCR1, value | BIT_TCR1_T1_TRAI);
fe->te_param.tx_yel_alarm = 1;
}
}else{
value = READ_REG(REG_E1TNAF);
if (!(value & BIT_E1TNAF_A)){
DEBUG_TE1("%s: Enable transmit RAI alarm\n",
fe->name);
WRITE_REG(REG_E1TNAF, value | BIT_E1TNAF_A);
fe->te_param.tx_yel_alarm = 1;
}
}
}
return 0;
}
/******************************************************************************
** sdla_ds_te1_clear_alarms()
**
** Description:
** Arguments:
** Returns:
*/
static int sdla_ds_te1_clear_alarms(sdla_fe_t* fe, u_int32_t alarms)
{
u8 value;
/* NC: Always set yellow alarm no need to check whether
* yellow alarm is ignored */
if (alarms & WAN_TE_BIT_ALARM_YEL){
if (IS_T1_FEMEDIA(fe)){
value = READ_REG(REG_TCR1);
if (value & BIT_TCR1_T1_TRAI){
DEBUG_EVENT("%s: Disable transmit RAI alarm\n",
fe->name);
WRITE_REG(REG_TCR1, value & ~BIT_TCR1_T1_TRAI);
fe->te_param.tx_yel_alarm = 0;
}
}else{
value = READ_REG(REG_E1TNAF);
if (value & BIT_E1TNAF_A){
DEBUG_TE1("%s: Disable transmit RAI alarm\n",
fe->name);
WRITE_REG(REG_E1TNAF, value & ~BIT_E1TNAF_A);
fe->te_param.tx_yel_alarm = 0;
}
}
}
return 0;
}
/******************************************************************************
** sdla_ds_te1_clear_alarms()
**
** Description:
** Arguments:
** Returns:
*/
static int sdla_ds_te1_rbs_init(sdla_fe_t* fe)
{
int i;
if (IS_E1_FEMEDIA(fe)){
for(i = 1; i < 16; i++){
WRITE_REG(REG_TS1+i, 0xFF);
}
}else{
for(i = 0; i < 12; i++){
WRITE_REG(REG_TS1+i, 0xFF);
}
}
return 0;
}
/******************************************************************************
** sdla_ds_te1_clear_alarms()
**
** Description:
** Arguments:
** Returns:
*/
static int sdla_ds_te1_rbs_ctrl(sdla_fe_t* fe, u_int32_t ch_map, int enable)
{
u_int8_t value;
unsigned int ch, bit, off;
value = READ_REG(REG_TCR1);
if (IS_T1_FEMEDIA(fe)){
if (enable == WAN_TRUE){
value |= BIT_TCR1_T1_TSSE;
}else{
value &= ~BIT_TCR1_T1_TSSE;
}
}else{
if (enable == WAN_TRUE){
value |= BIT_TCR1_E1_T16S;
}else{
value &= ~BIT_TCR1_E1_T16S;
}
}
WRITE_REG(REG_TCR1, value);
for(ch = 1; ch <= fe->te_param.max_channels; ch++){
if (!wan_test_bit(ch, &ch_map)){
continue;
}
if (IS_T1_FEMEDIA(fe)){
bit = (ch-1) % 8;
off = (ch-1) / 8;
}else{
if (ch == 16) continue;
bit = ch % 8;
off = ch / 8;
}
value = READ_REG(REG_SSIE1+off);
if (enable == WAN_TRUE){
value |= (1<<bit);
}else{
value &= ~(1<<bit);
}
DEBUG_TE1("%s: Channel %d: SSIE=%02X Val=%02X\n",
fe->name, ch, REG_SSIE1+off, value);
WRITE_REG(REG_SSIE1+off, value);
}
return 0;
}
/******************************************************************************
** sdla_ds_te1_rbs_report()
**
** Description:
** Arguments:
** Returns:
******************************************************************************/
static int sdla_ds_te1_rbs_report(sdla_fe_t* fe)
{
sdla_t* card = (sdla_t*)fe->card;
int ch = 1, max_channels;
max_channels = fe->te_param.max_channels;
ch = (IS_E1_FEMEDIA(fe)) ? 0 : 1;
for(; ch <= max_channels; ch++) {
if (wan_test_bit(ch, &fe->te_param.rx_rbs_status)){
if (card->wandev.te_report_rbsbits){
card->wandev.te_report_rbsbits(
card,
ch,
fe->te_param.rx_rbs[ch]);
}
wan_clear_bit(ch, &fe->te_param.rx_rbs_status);
}
}
return 0;
}
/*
******************************************************************************
* sdla_ds_te1_read_rbsbits()
*
* Description:
* Arguments: channo: 1-24 for T1
* 1-32 for E1
* Returns:
******************************************************************************
*/
static unsigned char sdla_ds_te1_read_rbsbits(sdla_fe_t* fe, int channo, int mode)
{
sdla_t* card = (sdla_t*)fe->card;
int rs_offset = 0, range = 0;
unsigned char rbsbits = 0x00, status = 0x00;
if (wan_test_bit(WAN_TE1_SWIRQ_TYPE_ALARM_LOS, (void*)&fe->swirq_map) ||
wan_test_bit(WAN_TE1_SWIRQ_TYPE_ALARM_LOF, (void*)&fe->swirq_map)){
/* Keep the original values */
return 0;
}
if (IS_E1_FEMEDIA(fe)){
rs_offset = channo % 16;
range = 16;
}else{
rs_offset = (channo - 1) % 12;
range = 12;
}
rbsbits = READ_REG(REG_RS1 + rs_offset);
if (channo <= range){
rbsbits = (rbsbits >> 4) & 0x0F;
}else{
rbsbits &= 0xF;
}
if (rbsbits & BIT_RS_A) status |= WAN_RBS_SIG_A;
if (rbsbits & BIT_RS_B) status |= WAN_RBS_SIG_B;
if (rbsbits & BIT_RS_C) status |= WAN_RBS_SIG_C;
if (rbsbits & BIT_RS_D) status |= WAN_RBS_SIG_D;
if (mode & WAN_TE_RBS_UPDATE){
sdla_ds_te1_rbs_update(fe, channo, status);
}
if ((mode & WAN_TE_RBS_REPORT) && card->wandev.te_report_rbsbits){
card->wandev.te_report_rbsbits(
card,
channo,
status);
}
return status;
}
/*
******************************************************************************
* sdla_ds_te1_check_rbsbits()
*
* Description:
* Arguments:
* Returns:
******************************************************************************
*/
static int
sdla_ds_te1_check_rbsbits(sdla_fe_t* fe, int ch_base, unsigned int ts_map, int report)
{
sdla_t* card = (sdla_t*)fe->card;
unsigned char rs_status = 0x0, rbsbits = 0x00, bit_mask = 0x00;
int rs_reg = 0, rs_offset = 0;
int i = 0, channel, range = 12;
if (wan_test_bit(WAN_TE1_SWIRQ_TYPE_ALARM_LOS, (void*)&fe->swirq_map) ||
wan_test_bit(WAN_TE1_SWIRQ_TYPE_ALARM_LOF, (void*)&fe->swirq_map)){
/* Keep the original values */
return 0;
}
switch(ch_base){
case 1:
rs_reg = REG_RSS1;
break;
case 9:
rs_reg = REG_RSS2;
break;
case 17:
rs_reg = REG_RSS3;
break;
case 25:
rs_reg = REG_RSS4;
break;
}
rs_status = READ_REG(rs_reg);
if (rs_status == 0x00){
return 0;
}
if (IS_E1_FEMEDIA(fe)){
range = 16;
}
for(i = 0; i < 8; i ++) {
channel = ch_base + i;
if (IS_E1_FEMEDIA(fe)){
if (channel == 1 || channel == 17){
continue;
}
rs_offset = (channel - 1) % 16;
}else{
rs_offset = (channel - 1) % 12;
}
/* If this channel/timeslot is not selected, move to
* another channel/timeslot */
if (!wan_test_bit(channel-1, &ts_map)){
continue;
}
bit_mask = (1 << i);
if(rs_status & bit_mask) {
unsigned char abcd_status = 0x00;
rbsbits = READ_REG(REG_RS1 + rs_offset);
DEBUG_TE1("%s: Channel %d: RS=%X+%d Val=%02X\n",
fe->name, channel, REG_RS1, rs_offset, rbsbits);
if (channel > range){
rbsbits &= 0x0F;
}else{
rbsbits = (rbsbits >> 4) & 0x0F;
}
if (rbsbits & BIT_RS_A) abcd_status |= WAN_RBS_SIG_A;
if (rbsbits & BIT_RS_B) abcd_status |= WAN_RBS_SIG_B;
if (rbsbits & BIT_RS_C) abcd_status |= WAN_RBS_SIG_C;
if (rbsbits & BIT_RS_D) abcd_status |= WAN_RBS_SIG_D;
if (IS_E1_FEMEDIA(fe)){
channel--;
}
sdla_ds_te1_rbs_update(fe, channel, abcd_status);
if (report && card->wandev.te_report_rbsbits){
card->wandev.te_report_rbsbits(
card,
channel,
abcd_status);
}
WRITE_REG(rs_reg, bit_mask);
}
}
return 0;
}
/*
******************************************************************************
* sdla_ds_te1_set_RBS()
*
* Description:
* Arguments: T1: 1-24 E1: 0-31
* Returns:
******************************************************************************
*/
static int
sdla_ds_te1_set_rbsbits(sdla_fe_t *fe, int channel, unsigned char status)
{
int ts_off = 0, range = 0;
unsigned char rbsbits = 0x00, ts_org;
if ((unsigned int)channel > fe->te_param.max_channels){
DEBUG_EVENT("%s: Invalid channel number %d (%d)\n",
fe->name, channel, fe->te_param.max_channels);
return -EINVAL;
}
#if 0
if (IS_E1_FEMEDIA(fe) && (channel == 0 || channel == 16)){
DEBUG_EVENT("%s: Invalid channel number %d for E1 Rx SIG\n",
fe->name, channel);
return 0;
}
#endif
if (status & WAN_RBS_SIG_A) rbsbits |= BIT_TS_A;
if (status & WAN_RBS_SIG_B) rbsbits |= BIT_TS_B;
if (!(IS_T1_FEMEDIA(fe) && WAN_FE_FRAME(fe) == WAN_FR_D4)){
if (status & WAN_RBS_SIG_C) rbsbits |= BIT_TS_C;
if (status & WAN_RBS_SIG_D) rbsbits |= BIT_TS_D;
}
if (fe->fe_debug & WAN_FE_DEBUG_RBS_TX_ENABLE){
DEBUG_EVENT("%s: %s:%-3d TX RBS A:%1d B:%1d C:%1d D:%1d\n",
fe->name,
FE_MEDIA_DECODE(fe),
channel,
(rbsbits & BIT_TS_A) ? 1 : 0,
(rbsbits & BIT_TS_B) ? 1 : 0,
(rbsbits & BIT_TS_C) ? 1 : 0,
(rbsbits & BIT_TS_D) ? 1 : 0);
}
if (rbsbits & BIT_TS_A){
wan_set_bit(channel,(unsigned long*)&fe->te_param.tx_rbs_A);
}else{
wan_clear_bit(channel,(unsigned long*)&fe->te_param.tx_rbs_A);
}
if (rbsbits & BIT_TS_B){
wan_set_bit(channel,(unsigned long*)&fe->te_param.tx_rbs_B);
}else{
wan_clear_bit(channel,(unsigned long*)&fe->te_param.tx_rbs_B);
}
if (rbsbits & BIT_TS_C){
wan_set_bit(channel,(unsigned long*)&fe->te_param.tx_rbs_C);
}else{
wan_clear_bit(channel,(unsigned long*)&fe->te_param.tx_rbs_C);
}
if (rbsbits & BIT_TS_D){
wan_set_bit(channel,(unsigned long*)&fe->te_param.tx_rbs_D);
}else{
wan_clear_bit(channel,(unsigned long*)&fe->te_param.tx_rbs_D);
}
if (IS_E1_FEMEDIA(fe)){
ts_off = channel % 16;
range = 15;
}else{
ts_off = (channel - 1) % 12;
range = 12;
}
ts_org = READ_REG(REG_TS1 + ts_off);
if (channel <= range){
rbsbits = rbsbits << 4;
ts_org &= 0xF;
}else{
ts_org &= 0xF0;
}
DEBUG_TE1("%s: TS=%02X Val=%02X\n",
fe->name,
REG_TS1+ts_off,
rbsbits);
WRITE_REG(REG_TS1 + ts_off, ts_org | rbsbits);
return 0;
}
/*
******************************************************************************
* sdla_te_rbs_update()
*
* Description:
* Arguments:
* Returns:
******************************************************************************
*/
static int
sdla_ds_te1_rbs_update(sdla_fe_t* fe, int channo, unsigned char status)
{
if (fe->fe_debug & WAN_FE_DEBUG_RBS_RX_ENABLE &&
fe->te_param.rx_rbs[channo] != status){
DEBUG_EVENT(
"%s: %s:%-3d RX RBS A:%1d B:%1d C:%1d D:%1d\n",
fe->name,
FE_MEDIA_DECODE(fe),
channo,
(status & WAN_RBS_SIG_A) ? 1 : 0,
(status & WAN_RBS_SIG_B) ? 1 : 0,
(status & WAN_RBS_SIG_C) ? 1 : 0,
(status & WAN_RBS_SIG_D) ? 1 : 0);
}
/* Update rbs value in private structures */
wan_set_bit(channo, &fe->te_param.rx_rbs_status);
fe->te_param.rx_rbs[channo] = status;
if (status & WAN_RBS_SIG_A){
wan_set_bit(channo,
(unsigned long*)&fe->te_param.rx_rbs_A);
}else{
wan_clear_bit(channo,
(unsigned long*)&fe->te_param.rx_rbs_A);
}
if (status & WAN_RBS_SIG_B){
wan_set_bit(channo,
(unsigned long*)&fe->te_param.rx_rbs_B);
}else{
wan_clear_bit(channo,
(unsigned long*)&fe->te_param.rx_rbs_B);
}
if (status & WAN_RBS_SIG_C){
wan_set_bit(channo,
(unsigned long*)&fe->te_param.rx_rbs_C);
}else{
wan_clear_bit(channo,
(unsigned long*)&fe->te_param.rx_rbs_C);
}
if (status & WAN_RBS_SIG_D){
wan_set_bit(channo,
(unsigned long*)&fe->te_param.rx_rbs_D);
}else{
wan_clear_bit(channo,
(unsigned long*)&fe->te_param.rx_rbs_D);
}
return 0;
}
/*
******************************************************************************
* sdla_te_rbs_print_banner()
*
* Description:
* Arguments:
* Returns:
******************************************************************************
*/
static int
sdla_ds_te1_rbs_print_banner(sdla_fe_t* fe)
{
if (IS_T1_FEMEDIA(fe)){
DEBUG_EVENT("%s: 111111111122222\n",
fe->name);
DEBUG_EVENT("%s: 123456789012345678901234\n",
fe->name);
DEBUG_EVENT("%s: ------------------------\n",
fe->name);
}else{
DEBUG_EVENT("%s: 11111111112222222222333\n",
fe->name);
DEBUG_EVENT("%s: 12345678901234567890123456789012\n",
fe->name);
DEBUG_EVENT("%s: --------------------------------\n",
fe->name);
}
return 0;
}
/*
******************************************************************************
* sdla_ds_te1_rbs_print_bits()
*
* Description:
* Arguments:
* Returns:
******************************************************************************
*/
static int
sdla_ds_te1_rbs_print_bits(sdla_fe_t* fe, unsigned long bits, char *msg)
{
int i, max_channels = fe->te_param.max_channels;
int start_chan = 1;
if (IS_E1_FEMEDIA(fe)){
start_chan = 0;
}
_DEBUG_EVENT("%s: %s ", fe->name, msg);
for(i=start_chan; i <= max_channels; i++)
_DEBUG_EVENT("%01d",
wan_test_bit(i, &bits) ? 1 : 0);
_DEBUG_EVENT("\n");
return 0;
}
/*
******************************************************************************
* sdla_ds_te1_rbs_print()
*
* Description:
* Arguments:
* Returns:
******************************************************************************
*/
static int
sdla_ds_te1_rbs_print(sdla_fe_t* fe, int last_status)
{
unsigned long rx_a = 0x00;
unsigned long rx_b = 0x00;
unsigned long rx_c = 0x00;
unsigned long rx_d = 0x00;
if (last_status){
rx_a = fe->te_param.rx_rbs_A;
rx_b = fe->te_param.rx_rbs_B;
rx_c = fe->te_param.rx_rbs_C;
rx_d = fe->te_param.rx_rbs_D;
DEBUG_EVENT("%s: Last Status:\n",
fe->name);
sdla_ds_te1_rbs_print_banner(fe);
sdla_ds_te1_rbs_print_bits(fe, fe->te_param.tx_rbs_A, "TX A:");
sdla_ds_te1_rbs_print_bits(fe, fe->te_param.tx_rbs_B, "TX B:");
sdla_ds_te1_rbs_print_bits(fe, fe->te_param.tx_rbs_C, "TX C:");
sdla_ds_te1_rbs_print_bits(fe, fe->te_param.tx_rbs_D, "TX D:");
DEBUG_EVENT("%s:\n", fe->name);
}else{
unsigned int i, chan = 0;
unsigned char abcd = 0x00;
for(i = 1; i <= fe->te_param.max_channels; i++) {
abcd = sdla_ds_te1_read_rbsbits(fe, i, WAN_TE_RBS_NONE);
chan = (IS_E1_FEMEDIA(fe))? i - 1 : i;
if (abcd & WAN_RBS_SIG_A){
wan_set_bit(chan, &rx_a);
}
if (abcd & WAN_RBS_SIG_B){
wan_set_bit(chan, &rx_b);
}
if (abcd & WAN_RBS_SIG_C){
wan_set_bit(chan, &rx_c);
}
if (abcd & WAN_RBS_SIG_D){
wan_set_bit(chan, &rx_d);
}
}
DEBUG_EVENT("%s: Current Status:\n",
fe->name);
sdla_ds_te1_rbs_print_banner(fe);
}
sdla_ds_te1_rbs_print_bits(fe, rx_a, "RX A:");
sdla_ds_te1_rbs_print_bits(fe, rx_b, "RX B:");
sdla_ds_te1_rbs_print_bits(fe, rx_c, "RX C:");
sdla_ds_te1_rbs_print_bits(fe, rx_d, "RX D:");
return 0;
}
/*
******************************************************************************
* sdla_ds_te1_intr_ctrl()
*
* Description: Check interrupt type.
* Arguments: card - pointer to device structure.
* write_register - write register function.
* read_register - read register function.
* Returns: None.
******************************************************************************
*/
static int
sdla_ds_te1_intr_ctrl(sdla_fe_t *fe, int dummy, u_int8_t type, u_int8_t mode, unsigned int ts_map)
{
unsigned char mask, value;
unsigned char rscse;
unsigned int ch, bit, off;
WAN_ASSERT(fe->write_fe_reg == NULL);
WAN_ASSERT(fe->read_fe_reg == NULL);
WAN_ASSERT(fe->fe_cfg.poll_mode == WANOPT_YES);
if (!wan_test_bit(TE_CONFIGURED,(void*)&fe->te_param.critical)){
return 0;
}
if (type & WAN_TE_INTR_GLOBAL){
mask = READ_REG(REG_GFIMR);
if (mode == WAN_FE_INTR_ENABLE){
mask |= (1<<WAN_DS_REGBITMAP(fe));
}else{
mask &= ~(1<<WAN_DS_REGBITMAP(fe));
}
WRITE_REG(REG_GFIMR, mask);
mask = READ_REG(REG_GLIMR);
if (mode == WAN_FE_INTR_ENABLE){
mask |= (1<<WAN_DS_REGBITMAP(fe));
}else{
mask &= ~(1<<WAN_DS_REGBITMAP(fe));
}
WRITE_REG(REG_GLIMR, mask);
mask = READ_REG(REG_GBIMR);
if (mode == WAN_FE_INTR_ENABLE){
mask |= (1<<WAN_DS_REGBITMAP(fe));
}else{
mask &= ~(1<<WAN_DS_REGBITMAP(fe));
}
WRITE_REG(REG_GBIMR, mask);
}
if (type & WAN_TE_INTR_BASIC){
if (mode == WAN_FE_INTR_ENABLE){
unsigned char mask = 0x00;
mask = BIT_RIM1_RAISC | BIT_RIM1_RAISD|
BIT_RIM1_RRAIC | BIT_RIM1_RRAID;
if (WAN_FE_FRAME(fe) != WAN_FR_UNFRAMED){
mask |= (BIT_RIM1_RLOFC | BIT_RIM1_RLOFD);
}
#if defined(FE_LOS_ENABLE)
mask |= (BIT_RIM1_RLOSC | BIT_RIM1_RLOSD);
#endif
WRITE_REG(REG_RIM1, mask);
WRITE_REG(REG_RLS1, 0xFF);
/* In-band loop codes */
if (IS_T1_FEMEDIA(fe)){
mask = BIT_RIM3_T1_LDNC|BIT_RIM3_T1_LDND |
BIT_RIM3_T1_LUPC|BIT_RIM3_T1_LUPD;
WRITE_REG(REG_RIM3, mask);
WRITE_REG(REG_RLS3, 0xFF);
}
//WRITE_REG(REG_RIM4, BIT_RIM4_TIMER);
WRITE_REG(REG_RLS4, 0xFF);
if (IS_T1_FEMEDIA(fe)){
mask = BIT_RIM7_T1_BC | BIT_RIM7_T1_BD;
/* mask |= BIT_RIM7_T1_RSLC96; */
WRITE_REG(REG_RIM7, mask);
}
WRITE_REG(REG_RLS7, 0xFF);
WRITE_REG(REG_LSIMR,
BIT_LSIMR_OCCIM | BIT_LSIMR_OCDIM |
BIT_LSIMR_SCCIM | BIT_LSIMR_SCCIM |
BIT_LSIMR_LOSCIM | BIT_LSIMR_LOSDIM |
BIT_LSIMR_JALTCIM | BIT_LSIMR_JALTSIM);
WRITE_REG(REG_LLSR, 0xFF);
}else{
WRITE_REG(REG_RIM1, 0x00);
WRITE_REG(REG_RIM2, 0x00);
WRITE_REG(REG_RIM3, 0x00);
WRITE_REG(REG_RIM4, 0x00);
WRITE_REG(REG_RIM5, 0x00);
WRITE_REG(REG_RIM7, 0x00);
WRITE_REG(REG_TIM1, 0x00);
WRITE_REG(REG_TIM2, 0x00);
WRITE_REG(REG_TIM3, 0x00);
WRITE_REG(REG_LSIMR, 0x00);
}
}
if (type & WAN_TE_INTR_SIGNALLING){
for(ch = 1; ch <= fe->te_param.max_channels; ch++){
if (!wan_test_bit(ch, &ts_map)){
continue;
}
if (IS_T1_FEMEDIA(fe)){
bit = (ch-1) % 8;
off = (ch-1) / 8;
}else{
if (ch == 16) continue;
bit = ch % 8;
off = ch / 8;
}
rscse = READ_REG(REG_RSCSE1+off);
if (mode == WAN_FE_INTR_ENABLE){
rscse |= (1<<bit);
}else{
rscse &= ~(1<<bit);
}
DEBUG_TE1("%s: Ch %d RSCSE=%02X Val=%02X\n",
fe->name, ch, REG_RSCSE1+off, rscse);
WRITE_REG(REG_RSCSE1+off, rscse);
}
value = READ_REG(REG_RIM4);
if (mode == WAN_FE_INTR_ENABLE){
value |= BIT_RIM4_RSCOS;
}else{
value &= ~BIT_RIM4_RSCOS;
}
WRITE_REG(REG_RIM4, value);
}
if (type & WAN_TE_INTR_PMON){
value = READ_REG(REG_ERCNT);
if (mode == WAN_FE_INTR_ENABLE){
value &= ~BIT_ERCNT_EAMS;
}else{
value |= BIT_ERCNT_EAMS;
}
WRITE_REG(REG_ERCNT, value);
}
return 0;
}
static int sdla_ds_te1_fr_rxintr_rls1(sdla_fe_t *fe, int silent)
{
unsigned char rim1 = READ_REG(REG_RIM1);
unsigned char rls1 = READ_REG(REG_RLS1);
unsigned char rrts1 = READ_REG(REG_RRTS1);
//if (WAN_FE_FRAME(fe) != WAN_FR_UNFRAMED){
if (rls1 & (BIT_RLS1_RRAIC|BIT_RLS1_RRAID)){
if (rrts1 & BIT_RRTS1_RRAI){
fe->fe_alarm |= WAN_TE_BIT_ALARM_RAI;
if (!silent) DEBUG_EVENT("%s: RAI alarm is ON\n",
fe->name);
}else{
fe->fe_alarm &= ~WAN_TE_BIT_ALARM_RAI;
if (!silent) DEBUG_EVENT("%s: RAI alarm is OFF\n",
fe->name);
}
}
//}
if (rim1 & (BIT_RIM1_RAISC|BIT_RIM1_RAISD)){
if (rls1 & (BIT_RLS1_RAISC|BIT_RLS1_RAISD)){
if (rrts1 & BIT_RRTS1_RAIS){
sdla_ds_te1_swirq_trigger(
fe,
WAN_TE1_SWIRQ_TYPE_ALARM_AIS,
WAN_TE1_SWIRQ_SUBTYPE_ALARM_ON,
WAN_T1_ALARM_THRESHOLD_AIS_ON);
}else{
sdla_ds_te1_swirq_trigger(
fe,
WAN_TE1_SWIRQ_TYPE_ALARM_AIS,
WAN_TE1_SWIRQ_SUBTYPE_ALARM_OFF,
WAN_T1_ALARM_THRESHOLD_AIS_OFF);
}
}
}
if (rim1 & (BIT_RIM1_RLOSC|BIT_RIM1_RLOSD)){
if (rls1 & (BIT_RLS1_RLOSC|BIT_RLS1_RLOSD)){
if (rrts1 & BIT_RRTS1_RLOS){
sdla_ds_te1_swirq_trigger(
fe,
WAN_TE1_SWIRQ_TYPE_ALARM_LOS,
WAN_TE1_SWIRQ_SUBTYPE_ALARM_ON,
WAN_T1_ALARM_THRESHOLD_LOS_ON);
}else{
sdla_ds_te1_swirq_trigger(
fe,
WAN_TE1_SWIRQ_TYPE_ALARM_LOS,
WAN_TE1_SWIRQ_SUBTYPE_ALARM_OFF,
WAN_T1_ALARM_THRESHOLD_LOS_OFF);
}
}
}
if (WAN_FE_FRAME(fe) != WAN_FR_UNFRAMED){
if (rim1 & (BIT_RIM1_RLOFC | BIT_RIM1_RLOFD)){
if (rls1 & (BIT_RLS1_RLOFC|BIT_RLS1_RLOFD)){
if (rrts1 & BIT_RRTS1_RLOF){
sdla_ds_te1_swirq_trigger(
fe,
WAN_TE1_SWIRQ_TYPE_ALARM_LOF,
WAN_TE1_SWIRQ_SUBTYPE_ALARM_ON,
WAN_T1_ALARM_THRESHOLD_LOF_ON);
}else{
sdla_ds_te1_swirq_trigger(
fe,
WAN_TE1_SWIRQ_TYPE_ALARM_LOF,
WAN_TE1_SWIRQ_SUBTYPE_ALARM_OFF,
WAN_T1_ALARM_THRESHOLD_LOF_OFF);
}
}
}
}
WRITE_REG(REG_RLS1, rls1);
return 0;
}
static int sdla_ds_te1_fr_rx_intr(sdla_fe_t *fe, int silent)
{
unsigned char istatus;
istatus = READ_REG(REG_RIIR);
if (istatus & BIT_RIIR_RLS1){
sdla_ds_te1_fr_rxintr_rls1(fe, silent);
}
if (istatus & BIT_RIIR_RLS2){
unsigned char rls2 = READ_REG(REG_RLS2);
if (!silent) DEBUG_TE1("%s: E1 RX Latched Status Register 2 %02X\n",
fe->name, rls2);
if (IS_T1_FEMEDIA(fe)){
if (rls2 & BIT_RLS2_T1_SEFE){
if (!silent) DEBUG_EVENT(
"%s: Receive Errored Framing Bits (2/6)!\n",
fe->name);
}
if (rls2 & BIT_RLS2_T1_FBE){
if (!silent) DEBUG_EVENT(
"%s: Receive Framing Bit error!\n",
fe->name);
}
}else{
if (rls2 & BIT_RLS2_E1_RSA1){
if (!silent) DEBUG_EVENT(
"%s: Receive Signalling All Ones Event!\n",
fe->name);
}
if (rls2 & BIT_RLS2_E1_RSA0){
if (!silent) DEBUG_EVENT(
"%s: Receive Signalling All Ones Event!\n",
fe->name);
}
if (rls2 & BIT_RLS2_E1_RCMF){
if (!silent) DEBUG_EVENT(
"%s: Receive CRC4 Multiframe Event!\n",
fe->name);
}
if (rls2 & BIT_RLS2_E1_RAF){
u8 rnaf = READ_REG(REG_E1RNAF);
if (!silent) DEBUG_EVENT(
"%s: Receive Align Frame Event!\n",
fe->name);
if (rnaf & BIT_E1RNAF_A){
fe->fe_alarm |= WAN_TE_BIT_ALARM_RAI;
if (!silent) DEBUG_EVENT("%s: RAI alarm is ON\n",
fe->name);
}else{
fe->fe_alarm &= ~WAN_TE_BIT_ALARM_RAI;
if (!silent) DEBUG_EVENT("%s: RAI alarm is OFF\n",
fe->name);
}
}
}
WRITE_REG(REG_RLS2, rls2);
}
if (istatus & BIT_RIIR_RLS3){
unsigned char rls3 = READ_REG(REG_RLS3);
unsigned char rrts3 = READ_REG(REG_RRTS3);
if (!silent) DEBUG_TE1("%s: RX Latched Status Register 3 %02X\n",
fe->name, rls3);
if (IS_T1_FEMEDIA(fe)){
if (rls3 & BIT_RLS3_T1_LORCC){
if (!silent) DEBUG_EVENT(
"%s: Loss of Receive Clock Condition Clear!\n",
fe->name);
}
if (rls3 & BIT_RLS3_T1_LORCD){
if (!silent) DEBUG_EVENT(
"%s: Loss of Receive Clock Condition Detect!\n",
fe->name);
}
if (rls3 & (BIT_RLS3_T1_LUPD|BIT_RLS3_T1_LUPC)){
if (rrts3 & BIT_RRTS3_T1_LUP){
if (!silent) DEBUG_EVENT(
"%s: Loop-Up Code Detected Condition Detect!\n",
fe->name);
sdla_ds_te1_set_lb(
fe,
WAN_TE1_LINELB_MODE,WAN_TE1_LB_ENABLE,
ENABLE_ALL_CHANNELS);
}else{
if (!silent) DEBUG_TE1(
"%s: Loop-Up Code Detected Condition Clear!\n",
fe->name);
}
}
if (rls3 & (BIT_RLS3_T1_LDND|BIT_RLS3_T1_LDNC)){
if (rrts3 & BIT_RRTS3_T1_LDN){
if (!silent) DEBUG_EVENT(
"%s: Loop-Down Code Detected Condition Detect!\n",
fe->name);
sdla_ds_te1_set_lb(
fe,
WAN_TE1_LINELB_MODE,WAN_TE1_LB_DISABLE,
ENABLE_ALL_CHANNELS);
}else{
if (!silent) DEBUG_TE1(
"%s: Loop-Down Code Detected Condition Clear!\n",
fe->name);
}
}
}else{
if (rls3 & BIT_RLS3_E1_LORCC){
if (!silent) DEBUG_EVENT(
"%s: Loss of Receive Clock Condition Clear!\n",
fe->name);
}
if (rls3 & BIT_RLS3_E1_LORCD){
if (!silent) DEBUG_EVENT(
"%s: Loss of Receive Clock Condition Detect!\n",
fe->name);
}
}
WRITE_REG(REG_RLS3, rls3);
}
if (istatus & BIT_RIIR_RLS4){
unsigned char rls4 = READ_REG(REG_RLS4);
if (!silent) DEBUG_TE1("%s: RX Latched Status Register 4 %02X\n",
fe->name, rls4);
if (rls4 & BIT_RLS4_RSCOS){
if (!silent) DEBUG_EVENT(
"%s: Receive Signalling status changed!\n",
fe->name);
sdla_ds_te1_check_rbsbits(fe, 1, ENABLE_ALL_CHANNELS, 1);
sdla_ds_te1_check_rbsbits(fe, 9, ENABLE_ALL_CHANNELS, 1);
sdla_ds_te1_check_rbsbits(fe, 17, ENABLE_ALL_CHANNELS, 1);
if (IS_E1_FEMEDIA(fe)){
sdla_ds_te1_check_rbsbits(fe, 25, ENABLE_ALL_CHANNELS, 1);
}
}
if (rls4 & BIT_RLS4_TIMER){
if (!silent) DEBUG_ISR(
"%s: Performance monitor counters have been updated!\n",
fe->name);
sdla_ds_te1_pmon(fe, WAN_FE_PMON_READ);
}
WRITE_REG(REG_RLS4, rls4);
}
if (istatus & BIT_RIIR_RLS5){
unsigned char rls5 = READ_REG(REG_RLS5);
if (!silent) DEBUG_TE1("%s: RX Latched Status Register 5 %02X\n",
fe->name, rls5);
if (rls5 & BIT_RLS5_ROVR){
if (!silent) DEBUG_EVENT("%s: Receive FIFO overrun (HDLC)!\n",
fe->name);
}
if (rls5 & BIT_RLS5_RHOBT){
if (!silent) DEBUG_EVENT("%s: Receive HDLC Opening Byte Event (HDLC)!\n",
fe->name);
}
if (rls5 & BIT_RLS5_RPE){
if (!silent) DEBUG_EVENT("%s: Receive Packet End Event (HDLC)!\n",
fe->name);
}
if (rls5 & BIT_RLS5_RPS){
if (!silent) DEBUG_EVENT("%s: Receive Packet Start Event (HDLC)!\n",
fe->name);
}
if (rls5 & BIT_RLS5_RHWMS){
if (!silent) DEBUG_EVENT("%s: Receive FIFO Above High Watermark Set Event (HDLC)!\n",
fe->name);
}
if (rls5 & BIT_RLS5_RNES){
if (!silent) DEBUG_EVENT("%s: Receive FIFO Not Empty Set Event (HDLC)!\n",
fe->name);
}
WRITE_REG(REG_RLS5, rls5);
}
#if 0
if (istatus & BIT_RIIR_RLS6){
}
#endif
if (istatus & BIT_RIIR_RLS7){
unsigned char rls7 = READ_REG(REG_RLS7);
if (IS_T1_FEMEDIA(fe)){
if (!silent) DEBUG_TE1("%s: RX Latched Status Register 7 %02X\n",
fe->name, rls7);
if (rls7 & BIT_RLS7_T1_RRAI_CI){
if (!silent) DEBUG_EVENT("%s: Receive RAI-CI Detect!\n",
fe->name);
}
if (rls7 & BIT_RLS7_T1_RAIS_CI){
if (!silent) DEBUG_EVENT("%s: Receive RAI-CI Detect!\n",
fe->name);
}
if (rls7 & BIT_RLS7_T1_RSLC96){
if (!silent) DEBUG_EVENT("%s: Receive SLC-96 Alignment Event!\n",
fe->name);
}
if (rls7 & BIT_RLS7_T1_RFDLF){
if (!silent) DEBUG_TE1("%s: Receive FDL Register Full Event!\n",
fe->name);
}
if (rls7 & BIT_RLS7_T1_BC){
if (!silent) DEBUG_TE1("%s: BOC Clear Event!\n",
fe->name);
sdla_ds_te1_boc(fe, 0);
}
if (rls7 & BIT_RLS7_T1_BD){
if (!silent) DEBUG_TE1("%s: BOC Detect Event!\n",
fe->name);
sdla_ds_te1_boc(fe, 1);
}
}else{
if (rls7 & BIT_RLS7_E1_Sa6CD){
if (!silent) DEBUG_EVENT("%s: Sa6 Codeword detect!\n",
fe->name);
sdla_ds_e1_sa6code(fe);
}
if (rls7 & BIT_RLS7_E1_SaXCD){
if (!silent) DEBUG_EVENT("%s: SaX bit change detect!\n",
fe->name);
sdla_ds_e1_sabits(fe);
}
}
WRITE_REG(REG_RLS7, rls7);
}
return 0;
}
static int sdla_ds_te1_fr_tx_intr(sdla_fe_t *fe, int silent)
{
unsigned char istatus;
unsigned char status;
istatus = READ_REG(REG_TIIR);
if (istatus & BIT_TIIR_TLS1){
status = READ_REG(REG_TLS1);
if (status & BIT_TLS1_TPDV){
if (!silent) DEBUG_EVENT(
"%s: Transmit Pulse Density Violation Event!\n",
fe->name);
}
if (status & BIT_TLS1_LOTCC){
if (!silent) DEBUG_EVENT(
"%s: Loss of Transmit Clock condition Clear!\n",
fe->name);
}
WRITE_REG(REG_TLS1, status);
}
if (istatus & BIT_TIIR_TLS2){
status = READ_REG(REG_TLS2);
WRITE_REG(REG_TLS2, status);
}
if (istatus & BIT_TIIR_TLS3){
status = READ_REG(REG_TLS3);
WRITE_REG(REG_TLS3, status);
}
return 0;
}
static int sdla_ds_te1_liu_intr(sdla_fe_t *fe, int silent)
{
unsigned char lsimr = READ_REG(REG_LSIMR);
unsigned char llsr = READ_REG(REG_LLSR);
unsigned char lrsr = READ_REG(REG_LRSR);
if (llsr & BIT_LLSR_JALTC && lsimr & BIT_LSIMR_JALTCIM){
if (!silent) DEBUG_TE1("%s: Jitter Attenuator Limit Trip Clear!\n",
fe->name);
}
if (llsr & BIT_LLSR_JALTS && lsimr & BIT_LSIMR_JALTSIM){
if (!silent) DEBUG_TE1("%s: Jitter Attenuator Limit Trip Set!\n",
fe->name);
}
if (llsr & (BIT_LLSR_OCC | BIT_LLSR_OCD)){
#if 0
if (IS_T1_FEMEDIA(fe) && WAN_TE1_LBO(fe) == LBO 5/6/7){
/* Use LRSR register to get real value. LLSR is not
** valid for these modes */
}
#endif
if (lrsr & BIT_LRSR_OCS){
if (!(fe->fe_alarm & WAN_TE_BIT_ALARM_LIU_OC)){
if (!silent) DEBUG_TE1("%s: Open Circuit is detected!\n",
fe->name);
fe->fe_alarm |= WAN_TE_BIT_ALARM_LIU_OC;
}
}else{
if (fe->fe_alarm & WAN_TE_BIT_ALARM_LIU_OC){
if (!silent) DEBUG_TE1("%s: Open Circuit is cleared!\n",
fe->name);
fe->fe_alarm &= ~WAN_TE_BIT_ALARM_LIU_OC;
}
}
}
if (llsr & (BIT_LLSR_SCC | BIT_LLSR_SCD)){
if (lrsr & BIT_LRSR_SCS){
if (!(fe->fe_alarm & WAN_TE_BIT_ALARM_LIU_SC)){
if (!silent) DEBUG_EVENT("%s: Short Circuit is detected!(%i)\n",
fe->name, __LINE__);
fe->fe_alarm |= WAN_TE_BIT_ALARM_LIU_SC;
}
}else{
if (fe->fe_alarm & WAN_TE_BIT_ALARM_LIU_SC){
if (!silent) DEBUG_EVENT("%s: Short Circuit is cleared!(%i)\n",
fe->name, __LINE__);
fe->fe_alarm &= ~WAN_TE_BIT_ALARM_LIU_SC;
}
}
}
if (lsimr & (BIT_LSIMR_LOSDIM|BIT_LSIMR_LOSCIM)){
if (llsr & (BIT_LLSR_LOSC | BIT_LLSR_LOSD)){
if (lrsr & BIT_LRSR_LOSS){
if (!(fe->fe_alarm & WAN_TE_BIT_ALARM_LIU_LOS)){
if (!silent) DEBUG_EVENT("%s: Lost of Signal is detected!\n",
fe->name);
fe->fe_alarm |= WAN_TE_BIT_ALARM_LIU_LOS;
}
}else{
if (fe->fe_alarm & WAN_TE_BIT_ALARM_LIU_LOS){
if (!silent) DEBUG_EVENT("%s: Lost of Signal is cleared!\n",
fe->name);
fe->fe_alarm &= ~WAN_TE_BIT_ALARM_LIU_LOS;
}
}
}
}
WRITE_REG(REG_LLSR, llsr);
return 0;
}
static int sdla_ds_te1_bert_intr(sdla_fe_t *fe, int silent)
{
unsigned char blsr = READ_REG(REG_BLSR);
unsigned char bsim = READ_REG(REG_BSIM);
if (blsr & BIT_BLSR_BBED && bsim & BIT_BSIM_BBED){
if (!silent && WAN_NET_RATELIMIT())
DEBUG_EVENT("%s: BERT bit error detected!\n",
fe->name);
}
if (blsr & BIT_BLSR_BBCO && bsim & BIT_BSIM_BBCO){
if (!silent) DEBUG_EVENT("%s: BERT Bit Counter overflows!\n",
fe->name);
}
if (blsr & BIT_BLSR_BECO && bsim & BIT_BSIM_BECO){
if (!silent) DEBUG_EVENT("%s: BERT Error Counter overflows!\n",
fe->name);
}
if (blsr & BIT_BLSR_BRA1 && bsim & BIT_BSIM_BRA1){
if (!silent) DEBUG_EVENT("%s: BERT Receive All-Ones Condition!\n",
fe->name);
}
if (blsr & BIT_BLSR_BRA0 && bsim & BIT_BSIM_BRA0){
if (!silent) DEBUG_EVENT("%s: BERT Receive All-Zeros Condition!\n",
fe->name);
}
if (blsr & BIT_BLSR_BRLOS && bsim & BIT_BSIM_BRLOS){
if (!silent && WAN_NET_RATELIMIT())
DEBUG_EVENT("%s: BERT Receive Loss of Synchronization Condition!\n",
fe->name);
wan_clear_bit(WAN_TE_BERT_FLAG_INLOCK, &fe->te_param.bert_flag);
}
if (blsr & BIT_BLSR_BSYNC && bsim & BIT_BSIM_BSYNC){
if (!silent && WAN_NET_RATELIMIT())
DEBUG_EVENT("%s: BERT in synchronization Condition!\n",
fe->name);
wan_set_bit(WAN_TE_BERT_FLAG_INLOCK, &fe->te_param.bert_flag);
}
WRITE_REG(REG_BLSR, blsr);
return 0;
}
static int sdla_ds_te1_check_intr(sdla_fe_t *fe)
{
unsigned char framer_istatus, framer_imask;
unsigned char liu_istatus, liu_imask;
unsigned char bert_istatus, bert_imask;
WAN_ASSERT(fe->write_fe_reg == NULL);
WAN_ASSERT(fe->read_fe_reg == NULL);
WAN_ASSERT(fe->fe_cfg.poll_mode == WANOPT_YES);
framer_istatus = __READ_REG(REG_GFISR);
framer_imask = __READ_REG(REG_GFIMR);
//if (framer_istatus & (1 << WAN_FE_LINENO(fe))){
if ((framer_istatus & (1 << WAN_DS_REGBITMAP(fe))) &&
(framer_imask & (1 << WAN_DS_REGBITMAP(fe)))) {
DEBUG_ISR("%s: Interrupt for line %d (FRAMER)\n",
fe->name, WAN_FE_LINENO(fe));
return 1;
}
liu_istatus = __READ_REG(REG_GLISR);
liu_imask = __READ_REG(REG_GLIMR);
//if (liu_istatus & (1 << WAN_FE_LINENO(fe))){
if ((liu_istatus & (1 << WAN_DS_REGBITMAP(fe))) &&
(liu_imask & (1 << WAN_DS_REGBITMAP(fe)))) {
DEBUG_ISR("%s: Interrupt for line %d (LIU)\n",
fe->name, WAN_FE_LINENO(fe));
return 1;
}
bert_istatus = __READ_REG(REG_GBISR);
bert_imask = __READ_REG(REG_GBIMR);
//if (bert_istatus & (1 << WAN_FE_LINENO(fe))){
if ((bert_istatus & (1 << WAN_DS_REGBITMAP(fe))) &&
(bert_imask & (1 << WAN_DS_REGBITMAP(fe)))) {
DEBUG_ISR("%s: Interrupt for line %d (BERT)\n",
fe->name, WAN_FE_LINENO(fe));
return 1;
}
DEBUG_ISR("%s: This interrupt not for this port %d\n",
fe->name,
WAN_FE_LINENO(fe)+1);
return 0;
}
static int sdla_ds_te1_intr(sdla_fe_t *fe)
{
u_int8_t framer_istatus, liu_istatus, bert_istatus;
u_int8_t device_id;
int silent = 0;
WAN_ASSERT(fe->write_fe_reg == NULL);
WAN_ASSERT(fe->read_fe_reg == NULL);
device_id = WAN_TE1_DEVICE_ID;
if (device_id == DEVICE_ID_BAD){
DEBUG_EVENT(
"%s: ERROR: Failed to verify Device id (silent mode)!\n",
fe->name);
silent = 1;
}
framer_istatus = READ_REG(REG_GFISR);
liu_istatus = READ_REG(REG_GLISR);
bert_istatus = READ_REG(REG_GBISR);
//if (framer_istatus & (1 << WAN_FE_LINENO(fe))){
if (framer_istatus & (1 << WAN_DS_REGBITMAP(fe))){
sdla_ds_te1_fr_rx_intr(fe, silent);
sdla_ds_te1_fr_tx_intr(fe, silent);
//WRITE_REG(REG_GFISR, (1<<WAN_FE_LINENO(fe)));
WRITE_REG(REG_GFISR, (1<<WAN_DS_REGBITMAP(fe)));
}
//if (liu_istatus & (1 << WAN_FE_LINENO(fe))){
if (liu_istatus & (1 << WAN_DS_REGBITMAP(fe))){
sdla_ds_te1_liu_intr(fe, silent);
//WRITE_REG(REG_GLISR, (1<<WAN_FE_LINENO(fe)));
WRITE_REG(REG_GLISR, (1<<WAN_DS_REGBITMAP(fe)));
}
//if (bert_istatus & (1 << WAN_FE_LINENO(fe))){
if (bert_istatus & (1 << WAN_DS_REGBITMAP(fe))){
sdla_ds_te1_bert_intr(fe, silent);
//WRITE_REG(REG_GBISR, (1<<WAN_FE_LINENO(fe)));
WRITE_REG(REG_GBISR, (1<<WAN_DS_REGBITMAP(fe)));
}
DEBUG_TE1("%s: FE Interrupt Alarms=0x%X\n",
fe->name,fe->fe_alarm);
#if 1
if (fe->fe_alarm & WAN_TE_BIT_ALARM_LIU_SC){
/* AL: March 1, 2006
** 1. Mask global FE intr
** 2. Disable automatic update */
sdla_ds_te1_intr_ctrl(
fe, 0,
(WAN_TE_INTR_GLOBAL|WAN_TE_INTR_BASIC|WAN_TE_INTR_PMON),
WAN_FE_INTR_MASK,
0x00);
/* Start LINKDOWN poll */
sdla_ds_te1_swirq_trigger(
fe,
WAN_TE1_SWIRQ_TYPE_LINK,
WAN_TE1_SWIRQ_SUBTYPE_LINKCRIT,
POLLING_TE1_TIMER*5);
return 0;
}
#endif
if (sdla_ds_te1_set_status(fe, fe->fe_alarm)){
if (fe->fe_status != FE_CONNECTED){
/* AL: March 1, 2006
** 1. Mask global FE intr
** 2. Disable automatic update */
sdla_ds_te1_intr_ctrl(
fe, 0,
(WAN_TE_INTR_GLOBAL|WAN_TE_INTR_BASIC|WAN_TE_INTR_PMON),
WAN_FE_INTR_MASK,
0x00);
/* Start LINKDOWN poll */
sdla_ds_te1_swirq_trigger(
fe,
WAN_TE1_SWIRQ_TYPE_LINK,
WAN_TE1_SWIRQ_SUBTYPE_LINKDOWN,
POLLING_TE1_TIMER*5);
}
}
return 0;
}
/*
******************************************************************************
* sdla_ds_te1_timer()
*
* Description:
* Arguments:
* Returns:
******************************************************************************
*/
#if defined(__NetBSD__) || defined(__FreeBSD__) || defined(__OpenBSD__)
static void sdla_ds_te1_timer(void* pfe)
#elif defined(__WINDOWS__)
static void sdla_ds_te1_timer(IN PKDPC Dpc, void* pfe, void* arg2, void* arg3)
#else
static void sdla_ds_te1_timer(unsigned long pfe)
#endif
{
sdla_fe_t *fe = (sdla_fe_t*)pfe;
sdla_t *card = (sdla_t*)fe->card;
wan_device_t *wandev = &card->wandev;
wan_smp_flag_t smp_flags;
int empty = 1;
if (wan_test_bit(TE_TIMER_KILL,(void*)&fe->te_param.critical)){
wan_clear_bit(TE_TIMER_RUNNING,(void*)&fe->te_param.critical);
return;
}
if (!wan_test_bit(TE_TIMER_RUNNING,(void*)&fe->te_param.critical)){
/* Somebody clear this bit */
DEBUG_EVENT("WARNING: %s: Timer bit is cleared (should never happened)!\n",
fe->name);
return;
}
wan_clear_bit(TE_TIMER_RUNNING,(void*)&fe->te_param.critical);
/* Enable hardware interrupt for TE1 */
wan_spin_lock_irq(&fe->lockirq,&smp_flags);
empty = WAN_LIST_EMPTY(&fe->event);
wan_spin_unlock_irq(&fe->lockirq,&smp_flags);
if (!empty || fe->swirq_map){
DEBUG_TEST("%s: TE1 timer!\n", fe->name);
if (wan_test_and_set_bit(TE_TIMER_EVENT_PENDING,(void*)&fe->te_param.critical)){
DEBUG_EVENT("%s: TE1 timer event is pending!\n", fe->name);
return;
}
if (wandev->fe_enable_timer){
wandev->fe_enable_timer(fe->card);
}else{
sdla_ds_te1_polling(fe);
}
}else{
sdla_ds_te1_add_timer(fe, POLLING_TE1_TIMER);
}
return;
}
/*
******************************************************************************
* sdla_ds_te1_add_timer()
*
* Description: Enable software timer interrupt in delay ms.
* Arguments: delay - (in ms)
* Returns:
******************************************************************************
*/
static int sdla_ds_te1_add_timer(sdla_fe_t* fe, unsigned long delay)
{
int err=0;
if (wan_test_bit(TE_TIMER_KILL,(void*)&fe->te_param.critical) ||
wan_test_bit(TE_TIMER_RUNNING,(void*)&fe->te_param.critical)) {
return 0;
}
//err = wan_add_timer(&fe->timer, delay * HZ / 1000);
err = wan_add_timer(&fe->timer, delay * HZ );
if (err){
/* Failed to add timer */
return -EINVAL;
}
wan_set_bit(TE_TIMER_RUNNING,(void*)&fe->te_param.critical);
return 0;
}
/*
******************************************************************************
* sdla_ds_te1_add_event()
*
* Description: Enable software timer interrupt in delay ms.
* Arguments:
* Returns:
******************************************************************************
*/
static int
sdla_ds_te1_add_event(sdla_fe_t *fe, sdla_fe_timer_event_t *event)
{
sdla_t *card = (sdla_t*)fe->card;
sdla_fe_timer_event_t *tevent = NULL;
wan_smp_flag_t smp_flags;
WAN_ASSERT_RC(card == NULL, -EINVAL);
if (wan_test_bit(TE_TIMER_EVENT_INPROGRESS,(void*)&fe->te_param.critical)){
DEBUG_EVENT("ADBG> %s: Event in progress...\n", fe->name);
return -EINVAL;
}
/* Creating event timer */
tevent = wan_malloc(sizeof(sdla_fe_timer_event_t));
if (tevent == NULL){
DEBUG_EVENT(
"%s: Failed to allocate memory for timer event!\n",
fe->name);
return -EINVAL;
}
memcpy(tevent, event, sizeof(sdla_fe_timer_event_t));
#if 0
DEBUG_EVENT("%s: %s:%d: ---------------START ----------------------\n",
fe->name, __FUNCTION__,__LINE__);
WARN_ON(1);
DEBUG_EVENT("%s: %s:%d: ---------------STOP ----------------------\n",
fe->name, __FUNCTION__,__LINE__);
#endif
wan_spin_lock_irq(&fe->lockirq,&smp_flags);
/* Set event from pending event map */
if (wan_test_and_set_bit(event->type,(void*)&fe->event_map)){
DEBUG_TE1("%s: WARNING: Event type %d is already pending!\n",
fe->name, event->type);
wan_spin_unlock_irq(&fe->lockirq, &smp_flags);
wan_free(tevent);
return -EINVAL;
}
tevent->start = SYSTEM_TICKS;
if (WAN_LIST_EMPTY(&fe->event)){
WAN_LIST_INSERT_HEAD(&fe->event, tevent, next);
}else{
sdla_fe_timer_event_t *tmp;
int cnt = 0;
WAN_LIST_FOREACH(tmp, &fe->event, next){
if (!WAN_LIST_NEXT(tmp, next)) break;
cnt ++;
}
if (tmp == NULL){
DEBUG_EVENT("%s: ERROR: Internal Error!!!\n", fe->name);
wan_clear_bit(event->type,(void*)&fe->event_map);
wan_spin_unlock_irq(&fe->lockirq, &smp_flags);
return -EINVAL;
}
if (cnt > WAN_FE_MAX_QEVENT_LEN){
DEBUG_EVENT("%s: ERROR: Too many events in event queue!\n",
fe->name);
DEBUG_EVENT("%s: ERROR: Dropping new event type %d!\n",
fe->name, event->type);
wan_clear_bit(event->type,(void*)&fe->event_map);
wan_spin_unlock_irq(&fe->lockirq, &smp_flags);
wan_free(tevent);
return -EINVAL;
}
WAN_LIST_INSERT_AFTER(tmp, tevent, next);
}
DEBUG_TEST("%s: Add new DS Event=0x%X (%d sec)\n",
fe->name, event->type,event->delay);
wan_spin_unlock_irq(&fe->lockirq, &smp_flags);
return 0;
}
/******************************************************************************
** sdla_ds_te1_swirq_link()
**
** Description:
** Arguments:
** Returns: 0 - There are no more event. Do not need to schedule sw timer
** number - delay to schedule next event.
******************************************************************************/
static int sdla_ds_te1_swirq_link(sdla_fe_t* fe)
{
sdla_t *card = (sdla_t*)fe->card;
sdla_fe_swirq_t *swirq;
int subtype = 0, delay = 0;
WAN_ASSERT(fe->swirq == NULL);
swirq = &fe->swirq[WAN_TE1_SWIRQ_TYPE_LINK];
if (!WAN_STIMEOUT(swirq->start, swirq->delay)){
/* Timeout is not expired yet */
DEBUG_TEST("%s: T1/E1 link swirq (%s) is not ready (%ld:%ld:%d)...\n",
fe->name, WAN_TE1_SWIRQ_SUBTYPE_DECODE(swirq->subtype),
swirq->start,SYSTEM_TICKS,swirq->delay*HZ);
wan_set_bit(WAN_TE1_SWIRQ_TYPE_LINK, (void*)&fe->swirq_map);
return 1;
}
DEBUG_TE1("%s: T1/E1 link swirq (%s)\n",
fe->name, WAN_TE1_SWIRQ_SUBTYPE_DECODE(swirq->subtype));
subtype = swirq->subtype;
switch(subtype){
case WAN_TE1_SWIRQ_SUBTYPE_LINKDOWN:
sdla_ds_te1_read_alarms(fe, WAN_FE_ALARM_READ|WAN_FE_ALARM_UPDATE);
if (fe->fe_alarm & WAN_TE_BIT_ALARM_LIU_SC){
/* Short circuit detected, go to LINKCRIT state */
subtype = WAN_TE1_SWIRQ_SUBTYPE_LINKCRIT;
delay = POLLING_TE1_TIMER;
break;
}
sdla_ds_te1_pmon(fe, WAN_FE_PMON_UPDATE|WAN_FE_PMON_READ);
sdla_ds_te1_set_status(fe, fe->fe_alarm);
if (fe->fe_status == FE_CONNECTED){
subtype = WAN_TE1_SWIRQ_SUBTYPE_LINKUP;
}
delay = POLLING_TE1_TIMER;
break;
case WAN_TE1_SWIRQ_SUBTYPE_LINKCRIT:
if (!sdla_ds_te1_read_crit_alarms(fe)){
subtype = WAN_TE1_SWIRQ_SUBTYPE_LINKDOWN;
}
delay = POLLING_TE1_TIMER;
break;
case WAN_TE1_SWIRQ_SUBTYPE_LINKUP:
/* ALEX:
** Do not update protocol front end state from TE_LINKDOWN_TIMER
** because it cause to stay longer in interrupt handler
** (critical for XILINX code) */
if (fe->fe_status == FE_CONNECTED){
if (card->wandev.te_link_state){
card->wandev.te_link_state(card);
}
if (fe->fe_cfg.poll_mode == WANOPT_YES){
subtype = WAN_TE1_SWIRQ_SUBTYPE_LINKREADY;
delay = POLLING_TE1_TIMER;
}else{
/* Read alarm status before enabling fe interrupt */
sdla_ds_te1_read_alarms(fe, WAN_FE_ALARM_READ|WAN_FE_ALARM_UPDATE);
/* Enable Basic Interrupt
** Enable automatic update pmon counters */
sdla_ds_te1_intr_ctrl(
fe, 0,
(WAN_TE_INTR_GLOBAL|WAN_TE_INTR_BASIC|WAN_TE_INTR_PMON),
WAN_FE_INTR_ENABLE,
0x00);
return 0;
}
}else{
subtype = WAN_TE1_SWIRQ_SUBTYPE_LINKDOWN;
delay = POLLING_TE1_TIMER;
}
break;
case WAN_TE1_SWIRQ_SUBTYPE_LINKREADY:
/* Only used in no interrupt driven front-end mode */
sdla_ds_te1_read_alarms(fe, WAN_FE_ALARM_READ|WAN_FE_ALARM_UPDATE);
if (fe->fe_alarm & WAN_TE_BIT_ALARM_LIU_SC){
/* Short circuit detected, go to LINKCRIT state */
subtype = WAN_TE1_SWIRQ_SUBTYPE_LINKCRIT;
delay = POLLING_TE1_TIMER;
break;
}
sdla_ds_te1_set_status(fe, fe->fe_alarm);
if (fe->fe_status != FE_CONNECTED){
subtype = WAN_TE1_SWIRQ_SUBTYPE_LINKDOWN;
}
delay = POLLING_TE1_TIMER;
break;
default:
return -EINVAL;
}
/* SW irq is pending */
wan_clear_bit(1, (void*)&swirq->pending);
sdla_ds_te1_swirq_trigger(fe, WAN_TE1_SWIRQ_TYPE_LINK, subtype, delay);
return 1;
}
/******************************************************************************
** sdla_ds_te1_swirq_alarm()
**
** Description:
** Arguments:
** Returns: 0 - There are no more event. Do not need to schedule sw timer
** number - delay to schedule next event.
******************************************************************************/
static int sdla_ds_te1_swirq_alarm(sdla_fe_t* fe, int type)
{
sdla_fe_swirq_t *swirq;
u_int32_t alarms = fe->fe_alarm;
int update = WAN_FALSE;
WAN_ASSERT(fe->swirq == NULL);
swirq = &fe->swirq[type];
DEBUG_TEST("%s: %s swirq (%s)\n",
fe->name,
WAN_TE1_SWIRQ_TYPE_DECODE(type),
WAN_TE1_SWIRQ_SUBTYPE_DECODE(swirq->subtype));
if (swirq->subtype == WAN_TE1_SWIRQ_SUBTYPE_ALARM_ON){
if (WAN_STIMEOUT(swirq->start, swirq->delay)){
/* Got real LOS alarm */
if (type == WAN_TE1_SWIRQ_TYPE_ALARM_AIS){
alarms |= WAN_TE_BIT_ALARM_AIS;
}else if (type == WAN_TE1_SWIRQ_TYPE_ALARM_LOS){
alarms |= WAN_TE_BIT_ALARM_LOS;
}else if (type == WAN_TE1_SWIRQ_TYPE_ALARM_LOF){
alarms |= WAN_TE_BIT_ALARM_LOF;
}
wan_clear_bit(1, (void*)&swirq->pending);
update = WAN_TRUE;
}else{
DEBUG_TEST("%s: %s swirq (%s) is not ready (%ld:%ld:%d)...\n",
fe->name,
WAN_TE1_SWIRQ_TYPE_DECODE(type),
WAN_TE1_SWIRQ_SUBTYPE_DECODE(swirq->subtype),
swirq->start,SYSTEM_TICKS,swirq->delay*HZ);
wan_set_bit(WAN_TE1_SWIRQ_TYPE_LINK, (void*)&fe->swirq_map);
return 1;
}
}else if (swirq->subtype == WAN_TE1_SWIRQ_SUBTYPE_ALARM_OFF){
if (WAN_STIMEOUT(swirq->start, swirq->delay)){
/* Clearing LOS alarm */
if (type == WAN_TE1_SWIRQ_TYPE_ALARM_AIS){
alarms &= ~WAN_TE_BIT_ALARM_AIS;
}else if (type == WAN_TE1_SWIRQ_TYPE_ALARM_LOS){
alarms &= ~WAN_TE_BIT_ALARM_LOS;
}else if (type == WAN_TE1_SWIRQ_TYPE_ALARM_LOF){
alarms &= ~WAN_TE_BIT_ALARM_LOF;
}
wan_clear_bit(1, (void*)&swirq->pending);
update = WAN_TRUE;
}else{
DEBUG_TEST("%s: %s swirq (%s) is not ready (%ld:%ld:%d)...\n",
fe->name,
WAN_TE1_SWIRQ_TYPE_DECODE(type),
WAN_TE1_SWIRQ_SUBTYPE_DECODE(swirq->subtype),
swirq->start,SYSTEM_TICKS,swirq->delay*HZ);
wan_set_bit(WAN_TE1_SWIRQ_TYPE_LINK, (void*)&fe->swirq_map);
return 1;
}
}
if (update == WAN_TRUE){
DEBUG_TEST("%s: %s swirq (%s) updating state ...\n",
fe->name,
WAN_TE1_SWIRQ_TYPE_DECODE(type),
WAN_TE1_SWIRQ_SUBTYPE_DECODE(swirq->subtype));
sdla_ds_te1_update_alarms(fe, alarms);
if (sdla_ds_te1_set_status(fe, fe->fe_alarm)){
if (fe->fe_status == FE_CONNECTED){
sdla_ds_te1_swirq_trigger(
fe,
WAN_TE1_SWIRQ_TYPE_LINK,
WAN_TE1_SWIRQ_SUBTYPE_LINKUP,
POLLING_TE1_TIMER);
}else{
sdla_ds_te1_swirq_trigger(
fe,
WAN_TE1_SWIRQ_TYPE_LINK,
WAN_TE1_SWIRQ_SUBTYPE_LINKDOWN,
POLLING_TE1_TIMER);
}
return 1;
}
}
return 0;
}
/******************************************************************************
** sdla_ds_te1_swirq_trigger()
**
** Description:
** Arguments:
** Returns: 0 - There are no more event. Do not need to schedule sw timer
** number - delay to schedule next event.
******************************************************************************/
static int sdla_ds_te1_swirq_trigger(sdla_fe_t* fe, int type, int subtype, int delay)
{
WAN_ASSERT(fe == NULL);
WAN_ASSERT(fe->swirq == NULL);
DEBUG_TE1("%s: Trigger %s swirq (%s) (%d:%d) ...\n",
fe->name,
WAN_TE1_SWIRQ_TYPE_DECODE(type),
WAN_TE1_SWIRQ_SUBTYPE_DECODE(subtype),
wan_test_bit(1, (void*)&fe->swirq[type].pending),
fe->swirq[type].subtype);
if (!wan_test_and_set_bit(1, (void*)&fe->swirq[type].pending)){
/* new swirq */
fe->swirq[type].subtype = (u8)subtype;
fe->swirq[type].start = SYSTEM_TICKS;
}else{
/* already in a process */
if (fe->swirq[type].subtype != subtype){
fe->swirq[type].subtype = (u8)subtype;
fe->swirq[type].start = SYSTEM_TICKS;
}
}
fe->swirq[type].delay = delay;
wan_set_bit(type, (void*)&fe->swirq_map);
return 0;
}
/******************************************************************************
** sdla_ds_te1_swirq()
**
** Description:
** Arguments:
** Returns: 0 - There are no more event. Do not need to schedule sw timer
** number - delay to schedule next event.
******************************************************************************/
static int sdla_ds_te1_swirq(sdla_fe_t* fe)
{
WAN_ASSERT(fe->swirq == NULL);
fe->swirq_map = 0;
if (wan_test_bit(1, (void*)&fe->swirq[WAN_TE1_SWIRQ_TYPE_LINK].pending)){
sdla_ds_te1_swirq_link(fe);
}
if (wan_test_bit(1, (void*)&fe->swirq[WAN_TE1_SWIRQ_TYPE_ALARM_AIS].pending)){
sdla_ds_te1_swirq_alarm(fe, WAN_TE1_SWIRQ_TYPE_ALARM_AIS);
}
if (wan_test_bit(1, (void*)&fe->swirq[WAN_TE1_SWIRQ_TYPE_ALARM_LOS].pending)){
sdla_ds_te1_swirq_alarm(fe, WAN_TE1_SWIRQ_TYPE_ALARM_LOS);
}
if (wan_test_bit(1, (void*)&fe->swirq[WAN_TE1_SWIRQ_TYPE_ALARM_LOF].pending)){
sdla_ds_te1_swirq_alarm(fe, WAN_TE1_SWIRQ_TYPE_ALARM_LOF);
}
return 0;
}
/******************************************************************************
** sdla_ds_te1_polling()
**
** Description:
** Arguments:
** Returns: 0 - There are no more event. Do not need to schedule sw timer
** number - delay to schedule next event.
******************************************************************************/
static int sdla_ds_te1_poll_events(sdla_fe_t* fe)
{
sdla_fe_timer_event_t *event;
wan_smp_flag_t smp_flags;
u_int8_t pending = 0;
wan_spin_lock_irq(&fe->lockirq,&smp_flags);
if (WAN_LIST_EMPTY(&fe->event)){
wan_spin_unlock_irq(&fe->lockirq,&smp_flags);
DEBUG_EVENT("%s: WARNING: No FE events in a queue!\n",
fe->name);
sdla_ds_te1_add_timer(fe, POLLING_TE1_TIMER);
return 0;
}
event = WAN_LIST_FIRST(&fe->event);
WAN_LIST_REMOVE(event, next);
/* Clear event from pending event map */
wan_clear_bit(event->type,(void*)&fe->event_map);
wan_spin_unlock_irq(&fe->lockirq,&smp_flags);
DEBUG_TE1("%s: TE1 Polling event:0x%02X State=%s!\n",
fe->name, event->type, WAN_FE_STATUS_DECODE(fe));
switch(event->type){
case TE_RBS_READ:
/* Physically read RBS status and print */
sdla_ds_te1_rbs_print(fe, 0);
break;
case TE_SET_RBS:
/* Set RBS bits */
DEBUG_TE1("%s: Set ABCD bits (%X) for channel %d!\n",
fe->name,
event->te_event.rbs_abcd,
event->te_event.rbs_channel);
sdla_ds_te1_set_rbsbits(fe,
event->te_event.rbs_channel,
event->te_event.rbs_abcd);
break;
case TE_RBS_ENABLE:
case TE_RBS_DISABLE:
if (event->type == TE_RBS_ENABLE){
sdla_ds_te1_rbs_ctrl(fe, event->te_event.ch_map, WAN_TRUE);
}else{
sdla_ds_te1_rbs_ctrl(fe, event->te_event.ch_map, WAN_FALSE);
}
break;
case TE_SET_LB_MODE:
sdla_ds_te1_set_lb(fe, event->te_event.lb_type, event->mode, ENABLE_ALL_CHANNELS);
break;
case TE_POLL_CONFIG:
DEBUG_EVENT("%s: Re-configuring %s Front-End chip...\n",
fe->name, FE_MEDIA_DECODE(fe));
if (sdla_ds_te1_chip_config(fe)){
DEBUG_EVENT("%s: Failed to re-configuring Front-End chip!\n",
fe->name);
break;
}
/* Do not enable interrupts here */
event->type = TE_LINKDOWN_TIMER;
event->delay = POLLING_TE1_TIMER;
pending = 1;
break;
#if 0
case TE_POLL_CONFIG_VERIFY:
DEBUG_EVENT("%s: Verifing %s Front-End chip configuration...\n",
fe->name, FE_MEDIA_DECODE(fe));
if (sdla_ds_te1_chip_config_verify(fe)){
DEBUG_EVENT("%s: Failed to verify Front-End chip configuration!\n",
fe->name);
}
break;
#endif
case TE_POLL_READ:
fe->te_param.reg_dbg_value = READ_REG(event->te_event.reg);
DEBUG_TE1("%s: Read %s Front-End Reg:%04X=%02X\n",
fe->name, FE_MEDIA_DECODE(fe),
event->te_event.reg,
fe->te_param.reg_dbg_value);
fe->te_param.reg_dbg_ready = 1;
#if 0
DEBUG_EVENT("%s: Reading %s Front-End Registers:\n",
fe->name, FE_MEDIA_DECODE(fe));
for(reg=0x0;reg<=0x1ff;reg++){
DEBUG_EVENT("%s: REG[%04X]=%02X\n",
fe->name, reg, READ_REG(reg));
}
DEBUG_EVENT("%s: Reading %s Front-End LIU Registers:\n",
fe->name, FE_MEDIA_DECODE(fe));
for(reg=0x1000;reg<=0x1007;reg++){
DEBUG_EVENT("%s: REG[%04X]=%02X\n",
fe->name, reg, READ_REG(reg));
}
DEBUG_EVENT("%s: Reading %s Front-End BERT Registers:\n",
fe->name, FE_MEDIA_DECODE(fe));
for(reg=0x1100;reg<=0x110F;reg++){
DEBUG_EVENT("%s: REG[%04X]=%02X\n",
fe->name, reg, READ_REG(reg));
}
#endif
break;
case TE_POLL_WRITE:
DEBUG_EVENT("%s: Write %s Front-End Reg:%04X=%02X\n",
fe->name, FE_MEDIA_DECODE(fe),
event->te_event.reg,
event->te_event.value);
WRITE_REG(event->te_event.reg, event->te_event.value);
break;
case TE_LINELB_TIMER:
if (IS_T1_FEMEDIA(fe)){
sdla_ds_te1_txlbcode_done(fe);
}
break;
case WAN_TE_POLL_BERT:
if (!sdla_ds_te1_bert_read_status(fe)){
pending = 1;
}
break;
default:
DEBUG_EVENT("%s: Unknown DS TE1 Polling type %02X\n",
fe->name, event->type);
break;
}
/* Add new event */
if (pending){
sdla_ds_te1_add_event(fe, event);
}
wan_clear_bit(TE_TIMER_EVENT_PENDING,(void*)&fe->te_param.critical);
if (event) wan_free(event);
return 0;
}
/******************************************************************************
** sdla_ds_te1_polling()
**
** Description:
** Arguments:
** Returns: 0 - There are no more event. Do not need to schedule sw timer
** number - delay to schedule next event.
******************************************************************************/
static int sdla_ds_te1_polling(sdla_fe_t* fe)
{
WAN_ASSERT_RC(fe->write_fe_reg == NULL, 0);
WAN_ASSERT_RC(fe->read_fe_reg == NULL, 0);
#if 0
DEBUG_EVENT("%s: %s:%d: ---------------START ----------------------\n",
fe->name, __FUNCTION__,__LINE__);
WARN_ON(1);
DEBUG_EVENT("%s: %s:%d: ---------------STOP ----------------------\n",
fe->name, __FUNCTION__,__LINE__);
#endif
if (fe->swirq_map){
sdla_ds_te1_swirq(fe);
}
if (!WAN_LIST_EMPTY(&fe->event)){
sdla_ds_te1_poll_events(fe);
}
wan_clear_bit(TE_TIMER_EVENT_PENDING,(void*)&fe->te_param.critical);
sdla_ds_te1_add_timer(fe, POLLING_TE1_TIMER);
return 0;
}
/******************************************************************************
* sdla_ds_te1_txlbcode_done()
*
* Description:
* Arguments:
* Returns:
******************************************************************************/
static int sdla_ds_te1_txlbcode_done(sdla_fe_t *fe)
{
if (WAN_FE_FRAME(fe) == WAN_FR_D4){
WRITE_REG(REG_TCR3, READ_REG(REG_TCR3) & ~BIT_TCR3_TLOOP);
WRITE_REG(REG_RIM3, BIT_RIM3_T1_LDNC|BIT_RIM3_T1_LUPC|BIT_RIM3_T1_LDND|BIT_RIM3_T1_LUPD);
}else if (WAN_FE_FRAME(fe) == WAN_FR_ESF){
WRITE_REG(REG_THC2, READ_REG(REG_THC2) & ~BIT_THC2_SBOC);
}else{
return -EINVAL;
}
wan_clear_bit(fe->te_param.lb_tx_mode, &fe->te_param.lb_mode_map);
DEBUG_TE1("%s: T1 %s loopback code sent.\n",
fe->name,
WAN_TE1_BOC_LB_CODE_DECODE(fe->te_param.lb_tx_code));
fe->te_param.lb_tx_cmd = 0x00;
fe->te_param.lb_tx_code = 0x00;
wan_clear_bit(LINELB_WAITING,(void*)&fe->te_param.critical);
return 0;
}
/*
******************************************************************************
* sdla_ds_te1_flush_pmon()
*
* Description: Flush Dallas performance monitoring counters
* Arguments:
* Returns:
******************************************************************************
*/
static int sdla_ds_te1_flush_pmon(sdla_fe_t *fe)
{
sdla_te_pmon_t *pmon = &fe->fe_stats.te_pmon;
sdla_ds_te1_pmon(fe, WAN_FE_PMON_UPDATE | WAN_FE_PMON_READ);
pmon->lcv_errors = 0;
pmon->oof_errors = 0;
pmon->bee_errors = 0;
pmon->crc4_errors = 0;
pmon->feb_errors = 0;
pmon->fas_errors = 0;
return 0;
}
/*
******************************************************************************
* sdla_ds_te1_pmon()
*
* Description: Read DLS performance monitoring counters
* Arguments:
* Returns:
******************************************************************************
*/
static int sdla_ds_te1_pmon(sdla_fe_t *fe, int action)
{
sdla_te_pmon_t *pmon = &fe->fe_stats.te_pmon;
u16 pmon1 = 0, pmon2 = 0, pmon3 = 0, pmon4 = 0;
WAN_ASSERT(fe->write_fe_reg == NULL);
WAN_ASSERT(fe->read_fe_reg == NULL);
if (IS_FE_PMON_UPDATE(action)){
unsigned char ercnt = READ_REG(REG_ERCNT);
WRITE_REG(REG_ERCNT, ercnt & ~BIT_ERCNT_MECU);
WP_DELAY(10);
WRITE_REG(REG_ERCNT, ercnt | BIT_ERCNT_MECU);
WP_DELAY(250);
WRITE_REG(REG_ERCNT, ercnt);
}
if (IS_FE_PMON_READ(action)){
pmon->mask = 0x00;
/* Line code violation count register */
pmon1 = READ_REG(REG_LCVCR1) << 8 | READ_REG(REG_LCVCR2);
/* Path code violation count for E1/T1 */
pmon2 = READ_REG(REG_PCVCR1) << 8 | READ_REG(REG_PCVCR2);
/* OOF Error for T1/E1 */
pmon3 = READ_REG(REG_FOSCR1) << 8 | READ_REG(REG_FOSCR2);
if (IS_E1_FEMEDIA(fe) && WAN_FE_FRAME(fe) == WAN_FR_CRC4){
/* E-bit counter (Far End Block Errors) for CRC4 */
pmon4 = READ_REG(REG_E1EBCR1) << 8 | READ_REG(REG_E1EBCR2);
}
pmon->lcv_diff = pmon1;
pmon->lcv_errors = pmon->lcv_errors + pmon1;
if (IS_T1_FEMEDIA(fe)){
pmon->mask = WAN_TE_BIT_PMON_LCV |
WAN_TE_BIT_PMON_BEE |
WAN_TE_BIT_PMON_OOF;
pmon->bee_diff = pmon2;
pmon->bee_errors = pmon->bee_errors + pmon2;
pmon->oof_diff = pmon3;
pmon->oof_errors = pmon->oof_errors + pmon3;
}else{
pmon->mask = WAN_TE_BIT_PMON_LCV |
WAN_TE_BIT_PMON_CRC4 |
WAN_TE_BIT_PMON_FAS |
WAN_TE_BIT_PMON_FEB;
pmon->crc4_diff = pmon2;
pmon->crc4_errors = pmon->crc4_errors + pmon2;
pmon->fas_diff = pmon3;
pmon->fas_errors = pmon->fas_errors + pmon3;
pmon->feb_diff = pmon4;
pmon->feb_errors = pmon->feb_errors + pmon4;
}
}
if (IS_FE_PMON_PRINT(action)){
DEBUG_EVENT("%s: Line Code Viilation:\t\t%d\n",
fe->name, pmon->lcv_errors);
if (IS_T1_FEMEDIA(fe)){
DEBUG_EVENT("%s: Bit error events:\t\t%d\n",
fe->name, pmon->bee_errors);
DEBUG_EVENT("%s: Frames out of sync:\t\t%d\n",
fe->name, pmon->oof_errors);
}else{
DEBUG_EVENT("%s: CRC4 errors:\t\t\t%d\n",
fe->name, pmon->crc4_errors);
DEBUG_EVENT("%s: Frame Alignment signal errors:\t%d\n",
fe->name, pmon->fas_errors);
DEBUG_EVENT("%s: Far End Block errors:\t\t%d\n",
fe->name, pmon->feb_errors);
}
}
return 0;
}
/******************************************************************************
* sdla_ds_te1_boc()
*
* Description:
* Arguments:
* Returns:
******************************************************************************/
static int sdla_ds_te1_boc(sdla_fe_t *fe, int mode)
{
unsigned char boc, lb_type, lb_mode;
boc = READ_REG(REG_T1RBOC);
if (!mode){
DEBUG_TE1("%s: BOC Clear Event (BOC=%02X)!\n",
fe->name, boc);
return 0;
}
DEBUG_TE1("%s: BOC Detect Event (BOC=%02X)!\n",
fe->name, boc);
switch(boc){
case LINELB_ACTIVATE_CODE:
case LINELB_DEACTIVATE_CODE:
case PAYLB_ACTIVATE_CODE:
case PAYLB_DEACTIVATE_CODE:
if (boc == LINELB_ACTIVATE_CODE || boc == LINELB_DEACTIVATE_CODE){
lb_type = WAN_TE1_LINELB_MODE;
if (wan_test_bit(WAN_TE1_TX_LINELB_MODE, &fe->te_param.lb_mode_map)){
return 0; /* skip ack */
}
}else{
lb_type = WAN_TE1_PAYLB_MODE;
if (wan_test_bit(WAN_TE1_TX_PAYLB_MODE, &fe->te_param.lb_mode_map)){
return 0; /* skip ack */
}
}
if (boc == LINELB_ACTIVATE_CODE || boc == PAYLB_ACTIVATE_CODE){
lb_mode = WAN_TE1_LB_ENABLE;
}else{
lb_mode = WAN_TE1_LB_DISABLE;
}
sdla_ds_te1_set_lb(fe, lb_type, lb_mode, ENABLE_ALL_CHANNELS);
DEBUG_TE1("%s: Received T1 %s %s code from far end.\n",
fe->name,
WAN_TE1_LB_ACTION_DECODE(lb_mode),
WAN_TE1_LB_MODE_DECODE(lb_type));
break;
case UNIVLB_DEACTIVATE_CODE:
DEBUG_EVENT("%s: Received T1 %s code from far end.(%08X)\n",
fe->name, WAN_TE1_BOC_LB_CODE_DECODE(boc),fe->te_param.lb_mode_map);
if (wan_test_bit(WAN_TE1_LINELB_MODE, &fe->te_param.lb_mode_map)){
sdla_ds_te1_set_lb(fe, WAN_TE1_LINELB_MODE, WAN_TE1_LB_DISABLE, ENABLE_ALL_CHANNELS);
}
if (wan_test_bit(WAN_TE1_PAYLB_MODE, &fe->te_param.lb_mode_map)){
sdla_ds_te1_set_lb(fe, WAN_TE1_PAYLB_MODE, WAN_TE1_LB_DISABLE, ENABLE_ALL_CHANNELS);
}
break;
default:
DEBUG_TE1("%s: Received Unsupport Bit-Oriented code %02X!\n",
fe->name, boc);
break;
}
return 0;
}
/******************************************************************************
* sdla_ds_e1_sabits()
*
* Description:
* Arguments:
* Returns:
******************************************************************************/
static int sdla_ds_e1_sabits(sdla_fe_t* fe)
{
u_int8_t sabits = READ_REG(REG_SaBITS);
DEBUG_EVENT("%s: Sa Bits: %d:%d:%d:%d:%d\n",
fe->name,
(sabits & BIT_SaBITS_Sa4) ? 1 : 0,
(sabits & BIT_SaBITS_Sa5) ? 1 : 0,
(sabits & BIT_SaBITS_Sa6) ? 1 : 0,
(sabits & BIT_SaBITS_Sa7) ? 1 : 0,
(sabits & BIT_SaBITS_Sa8) ? 1 : 0);
return 0;
}
/******************************************************************************
* sdla_ds_e1_sa6code()
*
* Description:
* Arguments:
* Returns:
******************************************************************************/
static int sdla_ds_e1_sa6code(sdla_fe_t* fe)
{
u_int8_t sa6code = READ_REG(REG_Sa6CODE);
switch(sa6code){
case 0x08: case 0x04: case 0x02: case 0x01:
DEBUG_EVENT("%s: Received Sa6_8 Sa6 codeword\n", fe->name);
break;
case 0x0A: case 0x05:
DEBUG_EVENT("%s: Received Sa6_C Sa6 codeword\n", fe->name);
break;
case 0x06: case 0x03: case 0x09:
DEBUG_EVENT("%s: Received Sa6_C Sa6 codeword\n", fe->name);
break;
case 0x0E: case 0x07: case 0x0B: case 0x0D:
DEBUG_EVENT("%s: Received Sa6_E Sa6 codeword\n", fe->name);
break;
case 0x0F:
DEBUG_EVENT("%s: Received Sa6_F Sa6 codeword\n", fe->name);
break;
default:
DEBUG_EVENT("%s: Received unknown Sa6 codeword\n", fe->name);
break;
}
DEBUG_EVENT("%s: Sa Bits: %d:%d:%d:%d:%d\n",
fe->name,
(sa6code & BIT_SaBITS_Sa4) ? 1 : 0,
(sa6code & BIT_SaBITS_Sa5) ? 1 : 0,
(sa6code & BIT_SaBITS_Sa6) ? 1 : 0,
(sa6code & BIT_SaBITS_Sa7) ? 1 : 0,
(sa6code & BIT_SaBITS_Sa8) ? 1 : 0);
return 0;
}
/******************************************************************************
* sdla_ds_te1_rxlevel()
*
* Description:
* Arguments:
* Returns:
******************************************************************************/
static int sdla_ds_te1_rxlevel(sdla_fe_t* fe)
{
int index = 0;
unsigned char rxlevel;
WAN_ASSERT(fe->write_fe_reg == NULL);
WAN_ASSERT(fe->read_fe_reg == NULL);
rxlevel = READ_REG(REG_LRSL);
index = (rxlevel >> REG_LRSL_SHIFT) & REG_LRSL_MASK;
memset(fe->fe_stats.u.te1_stats.rxlevel, 0, WAN_TE_RXLEVEL_LEN);
if (IS_T1_FEMEDIA(fe)){
memcpy( fe->fe_stats.u.te1_stats.rxlevel,
wan_t1_ds_rxlevel[index],
strlen(wan_t1_ds_rxlevel[index]));
}else{
memcpy( fe->fe_stats.u.te1_stats.rxlevel,
wan_e1_ds_rxlevel[index],
strlen(wan_e1_ds_rxlevel[index]));
}
return 0;
}
/*
******************************************************************************
* sdla_ds_te1_liu_alb()
*
* Description:
* Arguments:
* Returns:
******************************************************************************
*/
static int sdla_ds_te1_liu_alb(sdla_fe_t* fe, unsigned char cmd)
{
unsigned char value;
WAN_ASSERT(fe->write_fe_reg == NULL);
WAN_ASSERT(fe->read_fe_reg == NULL);
if (cmd == WAN_TE1_LB_ENABLE && WAN_TE1_CLK(fe) != WAN_MASTER_CLK){
DEBUG_EVENT("%s: ERROR: You must be configured to Master Clock to execute this Loopback type!\n",
fe->name);
return -EINVAL;
}
value = READ_REG(REG_LMCR);
if (cmd == WAN_TE1_LB_ENABLE){
value |= BIT_LMCR_ALB;
}else{
value &= ~BIT_LMCR_ALB;
}
WRITE_REG(REG_LMCR, value);
return 0;
}
/*
******************************************************************************
* sdla_ds_te1_liu_llb()
*
* Description:
* Arguments:
* Returns:
******************************************************************************
*/
static int sdla_ds_te1_liu_llb(sdla_fe_t* fe, unsigned char cmd)
{
unsigned char value;
WAN_ASSERT(fe->write_fe_reg == NULL);
WAN_ASSERT(fe->read_fe_reg == NULL);
if (cmd == WAN_TE1_LB_ENABLE && WAN_TE1_CLK(fe) != WAN_MASTER_CLK){
DEBUG_EVENT("%s: ERROR: You must be configured to Master Clock to execute this Loopback type!\n",
fe->name);
return -EINVAL;
}
value = READ_REG(REG_LMCR);
if (cmd == WAN_TE1_LB_ENABLE){
value |= BIT_LMCR_LLB;
}else{
value &= ~BIT_LMCR_LLB;
}
WRITE_REG(REG_LMCR, value);
return 0;
}
/*
******************************************************************************
* sdla_ds_te1_liu_rlb()
*
* Description:
* Arguments:
* Returns:
******************************************************************************
*/
static int sdla_ds_te1_liu_rlb(sdla_fe_t* fe, unsigned char cmd)
{
unsigned char value;
WAN_ASSERT(fe->write_fe_reg == NULL);
WAN_ASSERT(fe->read_fe_reg == NULL);
value = READ_REG(REG_LMCR);
if (cmd == WAN_TE1_LB_ENABLE){
value |= BIT_LMCR_RLB;
}else{
value &= ~BIT_LMCR_RLB;
}
WRITE_REG(REG_LMCR, value);
return 0;
}
/*
******************************************************************************
* sdla_ds_te1_fr_flb()
*
* Description:
* Arguments:
* Returns:
******************************************************************************
*/
static int sdla_ds_te1_fr_flb(sdla_fe_t* fe, unsigned char cmd)
{
unsigned char value;
WAN_ASSERT(fe->write_fe_reg == NULL);
WAN_ASSERT(fe->read_fe_reg == NULL);
if (cmd == WAN_TE1_LB_ENABLE && WAN_TE1_CLK(fe) != WAN_MASTER_CLK){
DEBUG_EVENT("%s: ERROR: You must be configured to Master Clock to execute this Loopback type!\n",
fe->name);
return -EINVAL;
}
value = READ_REG(REG_RCR3);
if (cmd == WAN_TE1_LB_ENABLE){
value |= BIT_RCR3_FLB;
}else{
value &= ~BIT_RCR3_FLB;
}
WRITE_REG(REG_RCR3, value);
return 0;
}
/*
******************************************************************************
* sdla_ds_te1_fr_plb()
*
* Description:
* Arguments:
* Returns:
******************************************************************************
*/
static int sdla_ds_te1_fr_plb(sdla_fe_t* fe, unsigned char cmd)
{
unsigned char value;
WAN_ASSERT(fe->write_fe_reg == NULL);
WAN_ASSERT(fe->read_fe_reg == NULL);
value = READ_REG(REG_RCR3);
if (cmd == WAN_TE1_LB_ENABLE){
value |= BIT_RCR3_PLB;
}else{
value &= ~BIT_RCR3_PLB;
}
WRITE_REG(REG_RCR3, value);
return 0;
}
/******************************************************************************
* sdla_ds_te1_tx_lb()
*
* Description:
* Arguments:
* Returns:
******************************************************************************/
static int
sdla_ds_te1_tx_lb(sdla_fe_t* fe, u_int8_t type, u_int8_t mode)
{
sdla_fe_timer_event_t fe_event;
int delay = 0;
WAN_ASSERT(fe->write_fe_reg == NULL);
WAN_ASSERT(fe->read_fe_reg == NULL);
if (!IS_T1_FEMEDIA(fe)){
DEBUG_TE1("%s: ERROR: Unsupported Loopback type %s!\n",
fe->name, WAN_TE1_LB_MODE_DECODE(type));
return WAN_FE_LBMODE_RC_FAILED;
}
if (wan_test_bit(LINELB_WAITING,(void*)&fe->te_param.critical)){
DEBUG_TE1("%s: Still waiting for far end to send loopback signal back!\n",
fe->name);
return WAN_FE_LBMODE_RC_TXBUSY;
}
if (WAN_TE1_CLK(fe) != WAN_MASTER_CLK){
DEBUG_EVENT("%s: ERROR: You must be configured to Master Clock to execute this Loopback type!\n",
fe->name);
return WAN_FE_LBMODE_RC_FAILED;
}
fe->te_param.lb_tx_mode = type;
fe->te_param.lb_tx_cmd = mode;
if (type == WAN_TE1_TX_LINELB_MODE){
if (mode == WAN_TE1_LB_ENABLE){
fe->te_param.lb_tx_code = LINELB_ACTIVATE_CODE;
}else{
fe->te_param.lb_tx_code = LINELB_DEACTIVATE_CODE;
}
}else if (type == WAN_TE1_TX_PAYLB_MODE){
if (mode == WAN_TE1_LB_ENABLE){
fe->te_param.lb_tx_code = PAYLB_ACTIVATE_CODE;
}else{
fe->te_param.lb_tx_code = PAYLB_DEACTIVATE_CODE;
}
}
DEBUG_TE1("%s: Sending T1 %s loopback code...\n",
fe->name, WAN_TE1_BOC_LB_CODE_DECODE(fe->te_param.lb_tx_code));
wan_set_bit(type, &fe->te_param.lb_mode_map);
if (WAN_FE_FRAME(fe) == WAN_FR_ESF){
delay = (WAN_T1_FDL_MSG_TIME * (WAN_T1_ESF_LINELB_TX_CNT + 1)) / 1000;
/* Start BOC transmition */
WRITE_REG(REG_T1TBOC, fe->te_param.lb_tx_code);
WRITE_REG(REG_THC2, READ_REG(REG_THC2) | BIT_THC2_SBOC);
}else if (WAN_FE_FRAME(fe) == WAN_FR_D4){
delay = (WAN_T1_FDL_MSG_TIME * (WAN_T1_D4_LINELB_TX_CNT + 1)) / 1000;
WRITE_REG(REG_RIM3, READ_REG(REG_RIM3) & ~(BIT_RIM3_T1_LDNC|BIT_RIM3_T1_LUPC|BIT_RIM3_T1_LDND|BIT_RIM3_T1_LUPD));
if (fe->te_param.lb_tx_cmd == WAN_TE1_LB_ENABLE){
WRITE_REG(REG_T1TCD1, 0x80);
WRITE_REG(REG_TCR4, 0x00);
}else{
WRITE_REG(REG_T1TCD1, 0x80);
WRITE_REG(REG_TCR4, BIT_TCR4_TC0);
}
WRITE_REG(REG_TCR3, READ_REG(REG_TCR3) | BIT_TCR3_TLOOP);
}
wan_set_bit(LINELB_WAITING,(void*)&fe->te_param.critical);
wan_set_bit(LINELB_CODE_BIT,(void*)&fe->te_param.critical);
wan_set_bit(LINELB_CHANNEL_BIT,(void*)&fe->te_param.critical);
fe_event.type = TE_LINELB_TIMER;
fe_event.delay = delay + 1;
sdla_ds_te1_add_event(fe, &fe_event);
return WAN_FE_LBMODE_RC_PENDING;
}
/******************************************************************************
* sdla_ds_te1_pclb()
*
* Description:
* Arguments:
* Returns:
******************************************************************************/
static int sdla_ds_te1_pclb(sdla_fe_t *fe, u_int8_t cmd, u_int32_t chan_map)
{
int off, shift, chan;
int channel_range = (IS_T1_FEMEDIA(fe)) ?
NUM_OF_T1_CHANNELS :
NUM_OF_E1_TIMESLOTS;
unsigned char val;
for(chan = 1; chan <= channel_range; chan++){
if (wan_test_bit(chan, &chan_map)){
off = (chan-1) / 8;
shift = (chan-1) % 8;
val = READ_REG(REG_PCL1+off);
WRITE_REG(REG_PCL1+off, val | (0x01 << shift));
}
}
return 0;
}
/******************************************************************************
* sdla_ds_te1_set_lb()
*
* Description:
* Arguments:
* Returns:
******************************************************************************/
static int
sdla_ds_te1_set_lb(sdla_fe_t *fe, u_int8_t type, u_int8_t mode, u_int32_t chan_map)
{
int err = 0;
WAN_ASSERT(fe->write_fe_reg == NULL);
WAN_ASSERT(fe->read_fe_reg == NULL);
if (!chan_map) chan_map = WAN_TE1_ACTIVE_CH(fe);
switch(type){
case WAN_TE1_LIU_ALB_MODE:
err = sdla_ds_te1_liu_alb(fe, mode);
break;
case WAN_TE1_LIU_LLB_MODE:
err = sdla_ds_te1_liu_llb(fe, mode);
break;
//case WAN_TE1_LIU_RLB_MODE:
// err = sdla_ds_te1_liu_rlb(fe, mode);
// break;
case WAN_TE1_LIU_DLB_MODE:
if (!(err = sdla_ds_te1_liu_llb(fe, mode))){
err = sdla_ds_te1_liu_rlb(fe, mode);
}
break;
case WAN_TE1_LIU_RLB_MODE:
case WAN_TE1_LINELB_MODE:
err = sdla_ds_te1_liu_rlb(fe, mode);
break;
case WAN_TE1_PAYLB_MODE:
err = sdla_ds_te1_fr_plb(fe, mode);
break;
case WAN_TE1_DDLB_MODE:
err = sdla_ds_te1_fr_flb(fe, mode);
break;
case WAN_TE1_PCLB_MODE:
err = sdla_ds_te1_pclb(fe, mode, chan_map);
break;
default:
DEBUG_EVENT("%s: Unsupported loopback type (%s) type=%d mode=%d!\n",
fe->name,
WAN_TE1_LB_MODE_DECODE(type),type,mode);
return -EINVAL;
}
if (err == WAN_FE_LBMODE_RC_SUCCESS){
if (mode == WAN_TE1_LB_ENABLE){
wan_set_bit(type, &fe->te_param.lb_mode_map);
}else{
wan_clear_bit(type, &fe->te_param.lb_mode_map);
}
}
DEBUG_EVENT("%s: %s %s mode ... %s\n",
fe->name,
WAN_TE1_LB_ACTION_DECODE(mode),
WAN_TE1_LB_MODE_DECODE(type),
(!err) ? "Done" : "Failed");
return err;
}
/******************************************************************************
* sdla_ds_te1_get_lbmode()
*
* Description:
* Arguments:
* Returns:
*****************************************************************************/
static u32 sdla_ds_te1_get_lbmode(sdla_fe_t *fe)
{
u32 type_map = 0;
u8 lmcr, rcr3;
WAN_ASSERT(fe->write_fe_reg == NULL);
WAN_ASSERT(fe->read_fe_reg == NULL);
lmcr = READ_REG(REG_LMCR);
if (lmcr & BIT_LMCR_ALB && lmcr & BIT_LMCR_LLB){
wan_set_bit(WAN_TE1_LIU_DLB_MODE, &type_map);
}else if (lmcr & BIT_LMCR_ALB){
wan_set_bit(WAN_TE1_LIU_ALB_MODE, &type_map);
}else if (lmcr & BIT_LMCR_LLB){
wan_set_bit(WAN_TE1_LIU_LLB_MODE, &type_map);
}
if (lmcr & BIT_LMCR_RLB) wan_set_bit(WAN_TE1_LINELB_MODE, &type_map);
rcr3 = READ_REG(REG_RCR3);
if (rcr3 & BIT_RCR3_FLB) wan_set_bit(WAN_TE1_DDLB_MODE, &type_map);
if (rcr3 & BIT_RCR3_PLB) wan_set_bit(WAN_TE1_PAYLB_MODE, &type_map);
/* Check remote loopback modes */
if (wan_test_bit(WAN_TE1_TX_PAYLB_MODE, &fe->te_param.lb_mode_map)){
wan_set_bit(WAN_TE1_TX_PAYLB_MODE, &type_map);
}
if (wan_test_bit(WAN_TE1_TX_LINELB_MODE, &fe->te_param.lb_mode_map)){
wan_set_bit(WAN_TE1_TX_LINELB_MODE, &type_map);
}
return type_map;
}
/******************************************************************************
* sdla_ds_te1_udp_lb()
*
* Description:
* Arguments:
* Returns:
*****************************************************************************/
static int sdla_ds_te1_udp_lb(sdla_fe_t *fe, char *data)
{
sdla_fe_lbmode_t *lb = (sdla_fe_lbmode_t*)data;
int err = 0;
lb->rc = WAN_FE_LBMODE_RC_SUCCESS;
if (lb->cmd == WAN_FE_LBMODE_CMD_SET){
switch(lb->type){
case WAN_TE1_TX_LINELB_MODE:
case WAN_TE1_TX_PAYLB_MODE:
lb->rc = (u8)sdla_ds_te1_tx_lb(fe, lb->type, lb->mode);
return 0;
break;
default:
err = sdla_ds_te1_set_lb(fe, lb->type, lb->mode, lb->chan_map);
break;
}
}else if (lb->cmd == WAN_FE_LBMODE_CMD_GET){
lb->type_map = sdla_ds_te1_get_lbmode(fe);
}
if (err) lb->rc = WAN_FE_LBMODE_RC_FAILED;
return 0;
}
/******************************************************************************
* sdla_ds_te1_udp_get_stats()
*
* Description:
* Arguments:
* Returns:
******************************************************************************/
static int
sdla_ds_te1_udp_get_stats(sdla_fe_t *fe, char *data,int force)
{
sdla_fe_stats_t *stats = (sdla_fe_stats_t*)&data[0];
/* TE1 Update T1/E1 perfomance counters */
sdla_ds_te1_pmon(fe, WAN_FE_PMON_UPDATE|WAN_FE_PMON_READ);
sdla_ds_te1_rxlevel(fe);
memcpy(stats, &fe->fe_stats, sizeof(sdla_fe_stats_t));
if (force){
/* force to read FE alarms */
DEBUG_EVENT("%s: Force to read Front-End alarms\n",
fe->name);
stats->alarms =
sdla_ds_te1_read_alarms(fe, WAN_FE_ALARM_READ);
}
/* Display Liu alarms */
stats->alarms |= WAN_TE_ALARM_LIU;
return 0;
}
/******************************************************************************
* sdla_ds_te1_bert_count()
*
* Description: should be called each second
* Arguments:
* Returns:
******************************************************************************/
static int sdla_ds_te1_bert_count(sdla_fe_t *fe)
{
u32 count;
u8 value;
DEBUG_TE1("%s: Reading BERT status ...\n", fe->name);
value = READ_REG(REG_BC1);
WRITE_REG(REG_BC1, value & ~BIT_BC1_LC);
WP_DELAY(1000);
WRITE_REG(REG_BC1, value | BIT_BC1_LC);
WP_DELAY(100);
/* Bit count */
count = READ_REG(REG_BBC1);
count |= (READ_REG(REG_BBC2) << 8);
count |= (READ_REG(REG_BBC3) << 16);
count |= (READ_REG(REG_BBC4) << 24);
DEBUG_TE1("%s: BERT Bit Count (diff) : %08X\n", fe->name, count);
fe->te_param.bert_stats.bit_cnt += count;
/* Error count */
count = READ_REG(REG_BEC1);
count |= (READ_REG(REG_BEC2) << 8);
count |= (READ_REG(REG_BEC3) << 16);
DEBUG_TE1("%s: BERT Error Count (diff): %08X\n", fe->name, count);
fe->te_param.bert_stats.err_cnt += count;
if (count){
fe->te_param.bert_stats.err_sec++;
}else{
fe->te_param.bert_stats.err_free_sec++;
}
fe->te_param.bert_stats.avail_sec++;
return 0;
}
/******************************************************************************
* sdla_ds_te1_bert_reset()
*
* Description:
* Arguments:
* Returns:
******************************************************************************/
static int sdla_ds_te1_bert_reset(sdla_fe_t *fe)
{
if (!wan_test_bit(WAN_TE_BERT_FLAG_READY, &fe->te_param.bert_flag)){
return -EINVAL;
}
memset(&fe->te_param.bert_stats, 0, sizeof(sdla_te_bert_stats_t));
return 0;
}
/******************************************************************************
* sdla_ds_te1_bert_read_status()
*
* Description:
* Arguments:
* Returns:
******************************************************************************/
static int sdla_ds_te1_bert_read_status(sdla_fe_t *fe)
{
if (!wan_test_bit(WAN_TE_BERT_FLAG_READY, &fe->te_param.bert_flag)){
return -EINVAL;
}
if (!wan_test_bit(WAN_TE_BERT_FLAG_INLOCK, &fe->te_param.bert_flag)){
return 0;
}
if (fe->fe_status != FE_CONNECTED){
return 0;
}
sdla_ds_te1_bert_count(fe);
return 0;
}
/******************************************************************************
* sdla_ds_te1_bert_status()
*
* Description:
* Arguments:
* Returns:
******************************************************************************/
static int sdla_ds_te1_bert_status(sdla_fe_t *fe, sdla_te_bert_stats_t *bert_stats)
{
if (wan_test_bit(WAN_TE_BERT_FLAG_INLOCK, &fe->te_param.bert_flag)){
fe->te_param.bert_stats.inlock = 1;
}else{
fe->te_param.bert_stats.inlock = 0;
}
if (fe->fe_status != FE_CONNECTED){
fe->te_param.bert_stats.inlock = 0; /* Force */
}
memcpy(bert_stats, &fe->te_param.bert_stats, sizeof(sdla_te_bert_stats_t));
return 0;
}
/******************************************************************************
* sdla_ds_te1_bert_stop()
*
* Description:
* Arguments:
* Returns:
******************************************************************************/
static int sdla_ds_te1_bert_stop(sdla_fe_t *fe)
{
DEBUG_EVENT("%s: Stopping Bit-Error-Test ...\n", fe->name);
WRITE_REG(REG_BSIM, 0x00);
WRITE_REG(REG_RXPC, READ_REG(REG_RXPC) & ~BIT_RXPC_RBPEN);
WRITE_REG(REG_TXPC, READ_REG(REG_TXPC) & ~BIT_TXPC_TBPEN);
WRITE_REG(REG_BC1, 0x00);
WRITE_REG(REG_BC2, 0x00);
WRITE_REG(REG_TBPCS1, 0x00);
WRITE_REG(REG_TBPCS2, 0x00);
WRITE_REG(REG_TBPCS3, 0x00);
WRITE_REG(REG_TBPCS4, 0x00);
WRITE_REG(REG_RBPCS1, 0x00);
WRITE_REG(REG_RBPCS2, 0x00);
WRITE_REG(REG_RBPCS3, 0x00);
WRITE_REG(REG_RBPCS4, 0x00);
wan_clear_bit(WAN_TE_BERT_FLAG_READY, &fe->te_param.bert_flag);
memset(&fe->te_param.bert_cfg, 0, sizeof(sdla_te_bert_cfg_t));
return 0;
}
/******************************************************************************
* sdla_ds_te1_bert_eib()
*
* Description:
* Arguments:
* Returns:
******************************************************************************/
static int sdla_ds_te1_bert_eib(sdla_fe_t *fe, sdla_te_bert_t *bert)
{
unsigned char value;
if (bert->un.cfg.eib == WAN_TE_BERT_EIB_NONE) return 0;
if (bert->cmd == WAN_TE_BERT_CMD_EIB){
if (!wan_test_bit(WAN_TE_BERT_FLAG_READY, &fe->te_param.bert_flag)){
return -EINVAL;
}
}else if (bert->cmd != WAN_TE_BERT_CMD_START){
/* Invalid BERT command */
return -EINVAL;
}
value = READ_REG(REG_BC2);
value &= ~(BIT_BC2_EIB2|BIT_BC2_EIB1|BIT_BC2_EIB0|BIT_BC2_SBE);
WRITE_REG(REG_BC2, value);
switch(bert->un.cfg.eib){
case WAN_TE_BERT_EIB_SINGLE:
value |= BIT_BC2_SBE;
break;
case WAN_TE_BERT_EIB1:
value |= BIT_BC2_EIB0;
break;
case WAN_TE_BERT_EIB2:
value |= BIT_BC2_EIB1;
break;
case WAN_TE_BERT_EIB3:
value |= (BIT_BC2_EIB1|BIT_BC2_EIB0);
break;
case WAN_TE_BERT_EIB4:
value |= BIT_BC2_EIB2;
break;
case WAN_TE_BERT_EIB5:
value |= (BIT_BC2_EIB2|BIT_BC2_EIB0);
break;
case WAN_TE_BERT_EIB6:
value |= (BIT_BC2_EIB2|BIT_BC2_EIB1);
break;
case WAN_TE_BERT_EIB7:
value |= (BIT_BC2_EIB2|BIT_BC2_EIB1|BIT_BC2_EIB0);
break;
}
WP_DELAY(100);
if (bert->cmd == WAN_TE_BERT_CMD_EIB){
DEBUG_EVENT("%s: Insert Bit Errors: %s\n",
fe->name, WAN_TE_BERT_EIB_DECODE(bert->un.cfg.eib));
}
WRITE_REG(REG_BC2, value);
return 0;
}
/******************************************************************************
* sdla_ds_te1_bert_config()
*
* Description:
* Arguments:
* Returns:
******************************************************************************/
static int sdla_ds_te1_bert_config(sdla_fe_t *fe, sdla_te_bert_t *bert)
{
sdla_fe_timer_event_t fevent;
unsigned long active_ch;
u8 rxpc, txpc, value;
int i = 0, channel_range = (IS_T1_FEMEDIA(fe)) ?
NUM_OF_T1_CHANNELS :
NUM_OF_E1_TIMESLOTS;
DEBUG_EVENT("%s: Starting Bit-Error-Test ...\n", fe->name);
if (bert->verbose){
DEBUG_EVENT("%s: BERT command : %s\n", fe->name, WAN_TE_BERT_CMD_DECODE(bert->cmd));
DEBUG_EVENT("%s: BERT channel list : %08X\n", fe->name, bert->un.cfg.chan_map);
DEBUG_EVENT("%s: BERT pattern type : %s\n", fe->name, WAN_TE_BERT_PATTERN_DECODE(bert->un.cfg.pattern_type));
DEBUG_EVENT("%s: BERT pattern length : %d\n", fe->name, bert->un.cfg.pattern_len);
DEBUG_EVENT("%s: BERT pattern : %08X\n",fe->name, bert->un.cfg.pattern);
DEBUG_EVENT("%s: BERT word count : %d\n", fe->name, bert->un.cfg.count);
DEBUG_EVENT("%s: BERT loopback mode : %s\n", fe->name, WAN_TE_BERT_LOOPBACK_DECODE(bert->un.cfg.lb_type));
DEBUG_EVENT("%s: BERT EIB : %s\n", fe->name, WAN_TE_BERT_EIB_DECODE(bert->un.cfg.eib));
}
memset(&fe->te_param.bert_stats, 0, sizeof(sdla_te_bert_stats_t));
/* Enable BERT */
rxpc = READ_REG(REG_RXPC);
txpc = READ_REG(REG_TXPC);
if (WAN_FE_FRAME(fe) == WAN_FR_UNFRAMED){
rxpc |= BIT_RXPC_RBPFUS;
txpc |= BIT_TXPC_TBPFUS;
}
WRITE_REG(REG_RXPC, rxpc | BIT_RXPC_RBPEN);
WRITE_REG(REG_TXPC, txpc | BIT_TXPC_TBPEN);
/* Channel assignment (def. all channels) */
WRITE_REG(REG_TBPCS1, 0x00);
WRITE_REG(REG_TBPCS2, 0x00);
WRITE_REG(REG_TBPCS3, 0x00);
WRITE_REG(REG_TBPCS4, 0x00);
WRITE_REG(REG_RBPCS1, 0x00);
WRITE_REG(REG_RBPCS2, 0x00);
WRITE_REG(REG_RBPCS3, 0x00);
WRITE_REG(REG_RBPCS4, 0x00);
active_ch = WAN_TE1_ACTIVE_CH(fe);
if (bert->un.cfg.chan_map == ENABLE_ALL_CHANNELS){
bert->un.cfg.chan_map = WAN_TE1_ACTIVE_CH(fe);
}
for(i = 1; i <= channel_range; i++){
int off, shift;
u_int8_t val;
if (wan_test_bit(i, (void*)&bert->un.cfg.chan_map) && wan_test_bit(i,(void*)&active_ch)){
off = (i-1) / 8;
shift = (i-1) % 8;
val = READ_REG(REG_TBPCS1+off);
WRITE_REG(REG_TBPCS1+off, val | (0x01 << shift));
val = READ_REG(REG_RBPCS1+off);
WRITE_REG(REG_RBPCS1+off, val | (0x01 << shift));
}
}
/* BERT pattern (def. preusorandom 2e7-1) */
value = 0;
switch(bert->un.cfg.pattern_type){
case WAN_TE_BERT_PATTERN_PSEUDORANDOM_2E7:
value = 0x00;
break;
case WAN_TE_BERT_PATTERN_PSEUDORANDOM_2E11:
value = BIT_BC1_PS0;
break;
case WAN_TE_BERT_PATTERN_PSEUDORANDOM_2E15:
value = BIT_BC1_PS1;
break;
case WAN_TE_BERT_PATTERN_PSEUDORANDOM_QRSS:
value = BIT_BC1_PS1 | BIT_BC1_PS0;
break;
case WAN_TE_BERT_PATTERN_REPETITIVE:
value = BIT_BC1_PS2;
if (bert->un.cfg.pattern_len > 32){
DEBUG_EVENT("%s: ERROR: Invalid BERT pattern length %d bits (0-32)!\n",
fe->name, bert->un.cfg.pattern_len);
return -EINVAL;
}
break;
case WAN_TE_BERT_PATTERN_WORD:
value = BIT_BC1_PS2 | BIT_BC1_PS0;
if (bert->un.cfg.count >= 256){
DEBUG_EVENT("%s: ERROR: Invalid BERT Alternating Word Count %d (1-256)!\n",
fe->name, bert->un.cfg.count);
return -EINVAL;
}
break;
case WAN_TE_BERT_PATTERN_DALY:
value = BIT_BC1_PS2 | BIT_BC1_PS1;
break;
case WAN_TE_BERT_PATTERN_PSEUDORANDOM_2E9:
value = BIT_BC1_PS2 | BIT_BC1_PS1 | BIT_BC1_PS0;
break;
default:
DEBUG_EVENT("%s: Error: Invalid BERT pattern type %s\n",
fe->name,
WAN_TE_BERT_PATTERN_DECODE(bert->un.cfg.pattern_type));
return -EINVAL;
}
WRITE_REG(REG_BC1, value);
/* BERT pattern string */
if (bert->un.cfg.pattern_type == WAN_TE_BERT_PATTERN_REPETITIVE){
u_int32_t pattern = bert->un.cfg.pattern;
int i = 0;
u16 repeat = 0;
if (bert->un.cfg.pattern_len < 17){
repeat = 32 / bert->un.cfg.pattern_len;
for(i=0; i < repeat; i++){
bert->un.cfg.pattern |= (pattern << bert->un.cfg.pattern_len);
}
bert->un.cfg.pattern_len *= repeat;
}
WRITE_REG(REG_BRP1, bert->un.cfg.pattern & 0xFF);
WRITE_REG(REG_BRP2, (bert->un.cfg.pattern >> 8) & 0xFF);
WRITE_REG(REG_BRP3, (bert->un.cfg.pattern >> 16) & 0xFF);
WRITE_REG(REG_BRP4, (bert->un.cfg.pattern >> 24) & 0xFF);
/* pattern length */
value = READ_REG(REG_BC2);
WRITE_REG(REG_BC2, value | (bert->un.cfg.pattern_len-17));
} else if (bert->un.cfg.pattern_type == WAN_TE_BERT_PATTERN_WORD){
WRITE_REG(REG_BRP1, bert->un.cfg.pattern & 0xFF);
WRITE_REG(REG_BRP2, (bert->un.cfg.pattern >> 8) & 0xFF);
WRITE_REG(REG_BRP3, bert->un.cfg.pattern & 0xFF);
WRITE_REG(REG_BRP4, (bert->un.cfg.pattern >> 8) & 0xFF);
WRITE_REG(REG_BAWC, bert->un.cfg.count/2);
}else{
WRITE_REG(REG_BRP1, 0xFF);
WRITE_REG(REG_BRP2, 0xFF);
WRITE_REG(REG_BRP3, 0xFF);
WRITE_REG(REG_BRP4, 0xFF);
}
/* EIB */
sdla_ds_te1_bert_eib(fe, bert);
/* Load pattern */
value = READ_REG(REG_BC1);
WRITE_REG(REG_BC1, value & ~BIT_BC1_TC);
WP_DELAY(1000);
WRITE_REG(REG_BC1, value | BIT_BC1_TC);
/* Force resynchronization */
value = READ_REG(REG_BC1);
WRITE_REG(REG_BC1, value & ~BIT_BC1_RESYNC);
WP_DELAY(1000);
WRITE_REG(REG_BC1, value | BIT_BC1_RESYNC);
/* Enable BERT events */
WRITE_REG(REG_BSIM, BIT_BSIM_BRLOS|BIT_BSIM_BSYNC);
/* Clear counters */
value = READ_REG(REG_BC1);
WRITE_REG(REG_BC1, value & ~BIT_BC1_LC);
WP_DELAY(1000);
WRITE_REG(REG_BC1, value | BIT_BC1_LC);
wan_set_bit(WAN_TE_BERT_FLAG_READY, &fe->te_param.bert_flag);
sdla_ds_te1_bert_reset(fe);
memcpy(&fe->te_param.bert_cfg, &bert->un.cfg, sizeof(sdla_te_bert_cfg_t));
fe->te_param.bert_start = SYSTEM_TICKS;
fevent.type = WAN_TE_POLL_BERT;
fevent.delay = POLLING_TE1_TIMER;
sdla_ds_te1_add_event(fe, &fevent);
return 0;
}
/******************************************************************************
* sdla_ds_te1_bert()
*
* Description:
* Arguments:
* Returns:
******************************************************************************/
static int sdla_ds_te1_bert(sdla_fe_t *fe, sdla_te_bert_t *bert)
{
switch(bert->cmd){
case WAN_TE_BERT_CMD_START:
if (wan_test_bit(WAN_TE_BERT_FLAG_READY, &fe->te_param.bert_flag)){
DEBUG_EVENT("%s: ERROR: BERT test is still running!\n",
fe->name);
bert->rc = WAN_TE_BERT_RC_RUNNING;
return 0;
}
break;
case WAN_TE_BERT_CMD_STOP:
case WAN_TE_BERT_CMD_EIB:
case WAN_TE_BERT_CMD_RESET:
if (!wan_test_bit(WAN_TE_BERT_FLAG_READY, &fe->te_param.bert_flag)){
DEBUG_EVENT("%s: ERROR: BERT test is not running!\n",
fe->name);
bert->rc = WAN_TE_BERT_RC_STOPPED;
return 0;
}
break;
case WAN_TE_BERT_CMD_STATUS:
case WAN_TE_BERT_CMD_RUNNING:
break;
default:
DEBUG_EVENT("%s: ERROR: Invalid BERT command (%02X)\n",
fe->name, bert->cmd);
bert->rc = WAN_TE_BERT_RC_EINVAL;
return 0;
}
if (bert->cmd == WAN_TE_BERT_CMD_STATUS){
if (wan_test_bit(WAN_TE_BERT_FLAG_READY, &fe->te_param.bert_flag)){
bert->status = WAN_TE_BERT_STATUS_RUNNING;
}else{
bert->status = WAN_TE_BERT_STATUS_STOPPED;
}
return sdla_ds_te1_bert_status(fe, &bert->un.stats);
}
if (bert->cmd == WAN_TE_BERT_CMD_RESET){
return sdla_ds_te1_bert_reset(fe);
}
if (bert->cmd == WAN_TE_BERT_CMD_RUNNING){
if (wan_test_bit(WAN_TE_BERT_FLAG_READY, &fe->te_param.bert_flag)){
bert->status = WAN_TE_BERT_STATUS_RUNNING;
}else{
bert->status = WAN_TE_BERT_STATUS_STOPPED;
}
return 0;
}
if (bert->cmd == WAN_TE_BERT_CMD_EIB){
return sdla_ds_te1_bert_eib(fe, bert);
}
if (bert->cmd == WAN_TE_BERT_CMD_STOP){
if (fe->te_param.bert_cfg.lb_type != WAN_TE_BERT_LOOPBACK_NONE){
bert->un.stop.chan_map = fe->te_param.bert_cfg.chan_map;
bert->un.stop.lb_type = fe->te_param.bert_cfg.lb_type;
}
sdla_ds_te1_bert_stop(fe);
return 0;
}
if (sdla_ds_te1_bert_config(fe, bert)){
bert->rc = WAN_TE_BERT_RC_EINVAL;
}
return 0;
}
/*
******************************************************************************
* sdla_ds_te1_udp()
*
* Description:
* Arguments:
* Returns:
******************************************************************************
*/
static int sdla_ds_te1_udp(sdla_fe_t *fe, void* p_udp_cmd, unsigned char* data)
{
wan_cmd_t *udp_cmd = (wan_cmd_t*)p_udp_cmd;
wan_femedia_t *fe_media;
sdla_fe_debug_t *fe_debug;
sdla_fe_timer_event_t event;
switch(udp_cmd->wan_cmd_command){
case WAN_GET_MEDIA_TYPE:
fe_media = (wan_femedia_t*)data;
memset(fe_media, 0, sizeof(wan_femedia_t));
fe_media->media = fe->fe_cfg.media;
fe_media->sub_media = fe->fe_cfg.sub_media;
fe_media->chip_id = WAN_TE_CHIP_DM;
fe_media->max_ports = fe->fe_max_ports;
udp_cmd->wan_cmd_return_code = WAN_CMD_OK;
udp_cmd->wan_cmd_data_len = sizeof(wan_femedia_t);
break;
case WAN_FE_LB_MODE:
/* Activate/Deactivate Line Loopback modes */
sdla_ds_te1_udp_lb(fe, data);
udp_cmd->wan_cmd_data_len = sizeof(sdla_fe_lbmode_t);
udp_cmd->wan_cmd_return_code = WAN_CMD_OK;
break;
case WAN_FE_GET_STAT:
sdla_ds_te1_udp_get_stats(fe, data, udp_cmd->wan_cmd_fe_force);
udp_cmd->wan_cmd_return_code = WAN_CMD_OK;
udp_cmd->wan_cmd_data_len = sizeof(sdla_fe_stats_t);
break;
case WAN_FE_FLUSH_PMON:
/* TE1 Flush T1/E1 pmon counters */
sdla_ds_te1_flush_pmon(fe);
udp_cmd->wan_cmd_return_code = WAN_CMD_OK;
break;
case WAN_FE_GET_CFG:
/* Read T1/E1 configuration */
memcpy(&data[0],
&fe->fe_cfg,
sizeof(sdla_fe_cfg_t));
udp_cmd->wan_cmd_return_code = WAN_CMD_OK;
udp_cmd->wan_cmd_data_len = sizeof(sdla_fe_cfg_t);
break;
case WAN_FE_SET_DEBUG_MODE:
fe_debug = (sdla_fe_debug_t*)&data[0];
switch(fe_debug->type){
case WAN_FE_DEBUG_RBS:
if (fe_debug->mode == WAN_FE_DEBUG_RBS_READ){
DEBUG_EVENT("%s: Reading RBS status!\n",
fe->name);
event.type = TE_RBS_READ;
event.delay = POLLING_TE1_TIMER;
sdla_ds_te1_add_event(fe, &event);
udp_cmd->wan_cmd_return_code = WAN_CMD_OK;
}else if (fe_debug->mode == WAN_FE_DEBUG_RBS_PRINT){
/* Enable extra debugging */
sdla_ds_te1_rbs_print(fe, 1);
udp_cmd->wan_cmd_return_code = WAN_CMD_OK;
}else if (fe_debug->mode == WAN_FE_DEBUG_RBS_RX_ENABLE){
/* Enable extra debugging */
DEBUG_EVENT("%s: Enable RBS RX DEBUG mode!\n",
fe->name);
fe->fe_debug |= WAN_FE_DEBUG_RBS_RX_ENABLE;
sdla_ds_te1_rbs_print(fe, 1);
udp_cmd->wan_cmd_return_code = WAN_CMD_OK;
}else if (fe_debug->mode == WAN_FE_DEBUG_RBS_TX_ENABLE){
/* Enable extra debugging */
DEBUG_EVENT("%s: Enable RBS TX DEBUG mode!\n",
fe->name);
fe->fe_debug |= WAN_FE_DEBUG_RBS_TX_ENABLE;
sdla_ds_te1_rbs_print(fe, 1);
udp_cmd->wan_cmd_return_code = WAN_CMD_OK;
}else if (fe_debug->mode == WAN_FE_DEBUG_RBS_RX_DISABLE){
/* Disable extra debugging */
DEBUG_EVENT("%s: Disable RBS RX DEBUG mode!\n",
fe->name);
fe->fe_debug &= ~WAN_FE_DEBUG_RBS_RX_ENABLE;
sdla_ds_te1_rbs_print(fe, 1);
udp_cmd->wan_cmd_return_code = WAN_CMD_OK;
}else if (fe_debug->mode == WAN_FE_DEBUG_RBS_TX_DISABLE){
/* Disable extra debugging */
DEBUG_EVENT("%s: Disable RBS TX DEBUG mode!\n",
fe->name);
fe->fe_debug &= ~WAN_FE_DEBUG_RBS_TX_ENABLE;
sdla_ds_te1_rbs_print(fe, 1);
udp_cmd->wan_cmd_return_code = WAN_CMD_OK;
}else if (fe_debug->mode == WAN_FE_DEBUG_RBS_SET){
if (IS_T1_FEMEDIA(fe)){
if (fe_debug->fe_debug_rbs.channel < 1 ||
fe_debug->fe_debug_rbs.channel > 24){
DEBUG_EVENT(
"%s: Invalid channel number %d\n",
fe->name,
fe_debug->fe_debug_rbs.channel);
break;
}
}else{
if (fe_debug->fe_debug_rbs.channel < 0 ||
fe_debug->fe_debug_rbs.channel > 31){
DEBUG_EVENT(
"%s: Invalid channel number %d\n",
fe->name,
fe_debug->fe_debug_rbs.channel);
break;
}
}
event.type = TE_SET_RBS;
event.delay = POLLING_TE1_TIMER;
event.te_event.rbs_channel = fe_debug->fe_debug_rbs.channel;
event.te_event.rbs_abcd = fe_debug->fe_debug_rbs.abcd;
sdla_ds_te1_add_event(fe, &event);
udp_cmd->wan_cmd_return_code = WAN_CMD_OK;
}
break;
case WAN_FE_DEBUG_RECONFIG:
event.type = TE_POLL_CONFIG;
event.delay = POLLING_TE1_TIMER;
sdla_ds_te1_add_event(fe, &event);
udp_cmd->wan_cmd_return_code = WAN_CMD_OK;
break;
#if 0
case WAN_FE_DEBUG_CONFIG_VERIFY:
event.type = TE_POLL_CONFIG_VERIFY;
event.delay = POLLING_TE1_TIMER;
sdla_ds_te1_add_event(fe, &event);
udp_cmd->wan_cmd_return_code = WAN_CMD_OK;
break;
#endif
case WAN_FE_DEBUG_REG:
if (fe->te_param.reg_dbg_busy){
if (fe_debug->fe_debug_reg.read == 2 && fe->te_param.reg_dbg_ready){
/* Poll the register value */
fe_debug->fe_debug_reg.value = fe->te_param.reg_dbg_value;
udp_cmd->wan_cmd_return_code = WAN_CMD_OK;
fe->te_param.reg_dbg_busy = 0;
}
break;
}
event.type = (fe_debug->fe_debug_reg.read) ?
TE_POLL_READ : TE_POLL_WRITE;
event.te_event.reg = (u_int16_t)fe_debug->fe_debug_reg.reg;
event.te_event.value = fe_debug->fe_debug_reg.value;
event.delay = POLLING_TE1_TIMER;
if (fe_debug->fe_debug_reg.read){
fe->te_param.reg_dbg_busy = 1;
fe->te_param.reg_dbg_ready = 0;
}
sdla_ds_te1_add_event(fe, &event);
udp_cmd->wan_cmd_return_code = WAN_CMD_OK;
break;
case WAN_FE_DEBUG_ALARM:
default:
udp_cmd->wan_cmd_return_code = WAN_UDP_INVALID_CMD;
break;
}
udp_cmd->wan_cmd_data_len = 0;
break;
case WAN_FE_TX_MODE:
fe_debug = (sdla_fe_debug_t*)&data[0];
switch(fe_debug->mode){
case WAN_FE_TXMODE_ENABLE:
DEBUG_EVENT("%s: Enable Transmitter!\n",
fe->name);
WRITE_REG(REG_LMCR, READ_REG(REG_LMCR) | BIT_LMCR_TE);
udp_cmd->wan_cmd_return_code = WAN_CMD_OK;
break;
case WAN_FE_TXMODE_DISABLE:
DEBUG_EVENT("%s: Disable Transmitter (tx tri-state mode)!\n",
fe->name);
WRITE_REG(REG_LMCR, READ_REG(REG_LMCR) & ~BIT_LMCR_TE);
udp_cmd->wan_cmd_return_code = WAN_CMD_OK;
break;
default:
udp_cmd->wan_cmd_return_code = WAN_UDP_INVALID_CMD;
udp_cmd->wan_cmd_data_len = 0;
break;
}
break;
case WAN_FE_BERT_MODE:
sdla_ds_te1_bert(fe, (sdla_te_bert_t*)&data[0]);
udp_cmd->wan_cmd_data_len = sizeof(sdla_te_bert_t);
udp_cmd->wan_cmd_return_code = WAN_CMD_OK;
break;
default:
udp_cmd->wan_cmd_return_code = WAN_UDP_INVALID_CMD;
udp_cmd->wan_cmd_data_len = 0;
break;
}
return 0;
}
static int
sdla_ds_te1_update_alarm_info(sdla_fe_t* fe, struct seq_file* m, int* stop_cnt)
{
#if !defined(__WINDOWS__)
PROC_ADD_LINE(m,
"=============================== %s Alarms ===============================\n",
FE_MEDIA_DECODE(fe));
PROC_ADD_LINE(m,
PROC_STATS_ALARM_FORMAT,
"ALOS", WAN_TE_PRN_ALARM_ALOS(fe->fe_alarm),
"LOS", WAN_TE_PRN_ALARM_LOS(fe->fe_alarm));
PROC_ADD_LINE(m,
PROC_STATS_ALARM_FORMAT,
"RED", WAN_TE_PRN_ALARM_RED(fe->fe_alarm),
"AIS", WAN_TE_PRN_ALARM_AIS(fe->fe_alarm));
if (IS_T1_FEMEDIA(fe)){
PROC_ADD_LINE(m,
PROC_STATS_ALARM_FORMAT,
"RAI", WAN_TE_PRN_ALARM_RAI(fe->fe_alarm),
"LOF", WAN_TE_PRN_ALARM_LOF(fe->fe_alarm));
}else{
PROC_ADD_LINE(m,
PROC_STATS_ALARM_FORMAT,
"LOF", WAN_TE_PRN_ALARM_LOF(fe->fe_alarm),
"RAI", WAN_TE_PRN_ALARM_RAI(fe->fe_alarm));
}
return m->count;
#endif
return 0;
}
static int
sdla_ds_te1_update_pmon_info(sdla_fe_t* fe, struct seq_file* m, int* stop_cnt)
{
#if !defined(__WINDOWS__)
PROC_ADD_LINE(m,
"=========================== %s PMON counters ============================\n",
FE_MEDIA_DECODE(fe));
if (IS_T1_FEMEDIA(fe)){
PROC_ADD_LINE(m,
PROC_STATS_PMON_FORMAT,
"Line Code Violation", fe->fe_stats.te_pmon.lcv_errors,
"Bit Errors", fe->fe_stats.te_pmon.bee_errors);
PROC_ADD_LINE(m,
PROC_STATS_PMON_FORMAT,
"Out of Frame Errors", fe->fe_stats.te_pmon.oof_errors,
"", (u_int32_t)0);
}else{
PROC_ADD_LINE(m,
PROC_STATS_PMON_FORMAT,
"Line Code Violation", fe->fe_stats.te_pmon.lcv_errors,
"CRC4 Errors", fe->fe_stats.te_pmon.crc4_errors);
PROC_ADD_LINE(m,
PROC_STATS_PMON_FORMAT,
"FAS Errors", fe->fe_stats.te_pmon.fas_errors,
"Far End Block Errors", fe->fe_stats.te_pmon.feb_errors);
}
return m->count;
#endif
return 0;
}