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

3776 lines
101 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.66 2007/04/10 16:28:49 sangoma Exp $
*/
/*
******************************************************************************
* sdla_8te1.c WANPIPE(tm) Multiprotocol WAN Link Driver.
* 8 ports T1/E1 board configuration.
*
* Author: Alex Feldman <al.feldman@sangoma.com>
*
* ============================================================================
* Feb 18, 2006 Alex Feldma Initial version.
******************************************************************************
*/
/******************************************************************************
* INCLUDE FILES
******************************************************************************/
#if defined(__NetBSD__) || defined(__FreeBSD__) || defined(__OpenBSD__)
# include <wanpipe_includes.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 */
# include <wanproc.h>
#elif (defined __WINDOWS__)
# include <wanpipe_includes.h>
# include <wanpipe_defines.h>
# include <wanpipe_debug.h>
# include <sdla_te1_ds.h>
# include <wanpipe.h> /* WANPIPE common user API definitions */
#define _DEBUG_EVENT DBG_8TE1
#elif (defined __LINUX__) || (defined __KERNEL__)
# include <linux/wanpipe_includes.h>
# include <linux/wanpipe_defines.h>
# include <linux/wanpipe_debug.h>
# include <linux/wanproc.h>
# if !defined(CONFIG_PRODUCT_WANPIPE_GENERIC)
# include <linux/wanpipe_snmp.h>
# endif
# include <linux/sdla_te1_ds.h>
# include <linux/wanpipe.h> /* WANPIPE common user API definitions */
#else
# error "No OS Defined"
#endif
/******************************************************************************
* DEFINES AND MACROS
******************************************************************************/
#undef WANPIPE_IGNORE_T1_YELLOW
/* Dec 14, 2007
** Disable all FE interrupt if Short Circuit condition detected! */
#undef WAN_FE_SC_DISABLE_INTR
#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
#if 1
/* Read/Write to front-end register */
#define WRITE_REG(reg,val) \
fe->write_fe_reg( \
fe->card, \
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( \
fe->card, \
fe_line_no, \
(int)sdla_ds_te1_address(fe,fe_line_no,(reg)), \
(int)(val))
#define READ_REG(reg) \
fe->read_fe_reg( \
fe->card, \
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( \
fe->card, \
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( \
fe->card, \
fe_line_no, \
(int)sdla_ds_te1_address(fe,fe_line_no,(reg)))
#else
/* Read/Write to front-end register */
#define WRITE_REG(reg,val) \
fe->write_fe_reg( \
fe->card, \
(int)((reg) + ((fe->fe_cfg.line_no)*(DLS_PORT_DELTA(reg)))),\
(int)(val))
#define WRITE_REG_LINE(fe_line_no, reg,val) \
fe->write_fe_reg( \
fe->card, \
(int)((reg) + (fe_line_no)*(DLS_PORT_DELTA(reg))), \
(int)(val))
#define READ_REG(reg) \
fe->read_fe_reg( \
fe->card, \
(int)((reg) + ((fe->fe_cfg.line_no)*(DLS_PORT_DELTA(reg)))))
#define __READ_REG(reg) \
fe->__read_fe_reg( \
fe->card, \
(int)((reg) + ((fe->fe_cfg.line_no)*(DLS_PORT_DELTA(reg)))))
#define READ_REG_LINE(fe_line_no, reg) \
fe->read_fe_reg( \
fe->card, \
(int)((reg) + (fe_line_no)*(DLS_PORT_DELTA(reg))))
#endif
#define WAN_TE1_FRAMED_ALARMS (WAN_TE_BIT_RED_ALARM | WAN_TE_BIT_OOF_ALARM)
#define WAN_TE1_UNFRAMED_ALARMS (WAN_TE_BIT_RED_ALARM | WAN_TE_BIT_LOS_ALARM)
#define IS_T1_ALARM(alarm) \
(alarm & \
( \
WAN_TE_BIT_RED_ALARM | \
WAN_TE_BIT_AIS_ALARM | \
WAN_TE_BIT_OOF_ALARM | \
WAN_TE_BIT_LOS_ALARM | \
WAN_TE_BIT_ALOS_ALARM \
))
#define IS_E1_ALARM(alarm) \
(alarm & \
( \
WAN_TE_BIT_RED_ALARM | \
WAN_TE_BIT_AIS_ALARM | \
WAN_TE_BIT_OOF_ALARM | \
WAN_TE_BIT_LOS_ALARM | \
WAN_TE_BIT_ALOS_ALARM \
))
#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_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, int, int, 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 unsigned int sdla_ds_te1_read_alarms(sdla_fe_t *fe, int read);
static int sdla_ds_te1_set_alarms(sdla_fe_t* fe, unsigned long alarms);
static int sdla_ds_te1_clear_alarms(sdla_fe_t* fe, unsigned long alarms);
static void sdla_ds_te1_set_status(sdla_fe_t* fe, unsigned long alarms);
static int sdla_ds_te1_print_alarms(sdla_fe_t*, unsigned int);
static int sdla_ds_te1_set_lbmode(sdla_fe_t*, unsigned char, unsigned char);
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_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*);
/******************************************************************************
* 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:
* Arguments:
* Returns:
******************************************************************************
*/
static int sdla_ds_te1_get_fe_status(sdla_fe_t *fe, unsigned char *status)
{
*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_iface)
{
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_lbmode;
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
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);
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,
value);
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: Enabling 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_TEST("%s: Enabling 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);
}
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);
WRITE_REG_LINE(0, REG_GLSRR, 0xFF);
WRITE_REG_LINE(0, REG_GFSRR, 0xFF);
WP_DELAY(1000);
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);
if (IS_FE_TXTRISTATE(fe)){
DEBUG_EVENT("%s: Tx Disabled (tri-state mode)\n",
fe->name);
}else{
/* 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));
if (IS_FE_TXTRISTATE(fe)){
DEBUG_EVENT("%s: Tx Disabled (tri-state mode)\n",
fe->name);
}else{
/* 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_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);
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);
}
}
if (WAN_FE_FRAME(fe) != WAN_FR_UNFRAMED){
/* Set INIT_DONE (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);
}
/* 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:
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_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 (High Impedence mode).\n",
fe->name,
WAN_TE1_RX_SLEVEL_DECODE(fe->fe_cfg.cfg.te_cfg.rx_slevel));
}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:
value |= (BIT_LRISMR_RSMS1 | BIT_LRISMR_RSMS0);
break;
default: /* set default value */
fe->fe_cfg.cfg.te_cfg.rx_slevel = WAN_TE1_RX_SLEVEL_12_DB;
break;
}
DEBUG_EVENT("%s: Rx Sensitivity Gain %s.\n",
fe->name,
WAN_TE1_RX_SLEVEL_DECODE(fe->fe_cfg.cfg.te_cfg.rx_slevel));
}
if (IS_T1_FEMEDIA(fe)){
WRITE_REG(REG_LRISMR, 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);
}
/* 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
/* Turn on LIU output */
WRITE_REG(REG_LMCR, BIT_LMCR_TE);
return 0;
}
/*
******************************************************************************
* 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;
WAN_ASSERT(fe->write_fe_reg == NULL);
WAN_ASSERT(fe->read_fe_reg == NULL);
/* Initial FE state */
fe->fe_status = FE_UNITIALIZED; //FE_DISCONNECTED;
WAN_LIST_INIT(&fe->event);
wan_spin_lock_init(&fe->lock);
/* 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;
}
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, Ch %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 (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);
/* LIU alarms are available in A108 */
fe->fe_stats.liu_alarms = WAN_TE_BIT_LIU_ALARM;
wan_set_bit(TE_CONFIGURED,(void*)&fe->te_param.critical);
/* Enable interrupts */
sdla_ds_te1_intr_ctrl(fe, 0, WAN_TE_INTR_GLOBAL, WAN_FE_INTR_ENABLE, 0x00);
/* Enable manual update pmon counter */
sdla_ds_te1_intr_ctrl(fe, 0, WAN_TE_INTR_PMON, WAN_FE_INTR_MASK, 0x00);
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;
sdla_fe_timer_event_t event;
/* 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 */
event.type = TE_LINKDOWN_TIMER;
event.delay = POLLING_TE1_TIMER;
sdla_ds_te1_add_event(fe, &event);
sdla_ds_te1_add_timer(fe, HZ);
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;
wan_smp_flag_t smp_flags;
/* 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);
wan_spin_lock_irq(&fe->lock,&smp_flags);
while(!WAN_LIST_EMPTY(&fe->event)){
fe_event = WAN_LIST_FIRST(&fe->event);
WAN_LIST_REMOVE(fe_event, next);
if (fe_event) wan_free(fe_event);
}
wan_spin_unlock_irq(&fe->lock,&smp_flags);
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: Front-End timer is not stopped!\n",
fe->name);
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);
/* 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;
/* FIXME: Alex to disable interrupts here */
sdla_ds_te1_intr_ctrl(fe, 0, WAN_TE_INTR_GLOBAL, WAN_FE_INTR_MASK, 0x00);
sdla_ds_te1_intr_ctrl(fe, 0, WAN_TE_INTR_BASIC, WAN_FE_INTR_MASK, 0x00);
sdla_ds_te1_intr_ctrl(fe, 0, 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 int sdla_ds_t1_is_alarm(sdla_fe_t *fe, unsigned long alarms)
{
/* NC: Bring the link down if we re in SC mode */
if (fe->liu_alarm & WAN_TE_BIT_LIU_ALARM_SC){
return 1;
}
return (alarms & WAN_TE1_FRAMED_ALARMS);
}
/******************************************************************************
** sdla_ds_e1_is_alarm()
**
** Description: Verify E1 status.
** Arguments:
** Returns: 1 - the port is connected
** 0 - the port is disconnected
******************************************************************************/
static int sdla_ds_e1_is_alarm(sdla_fe_t *fe, unsigned long alarms)
{
if (WAN_FE_FRAME(fe) == WAN_FR_UNFRAMED){
if (!fe->te_param.lb_mode &&
(fe->liu_alarm & WAN_TE_BIT_LIU_ALARM_OC ||
fe->liu_alarm & WAN_TE_BIT_LIU_ALARM_SC ||
fe->liu_alarm & WAN_TE_BIT_LIU_ALARM_LOS)){
return 1;
}
return (alarms & WAN_TE1_UNFRAMED_ALARMS);
}
/* NC: Bring the link down if we re in SC mode */
if (fe->liu_alarm & WAN_TE_BIT_LIU_ALARM_SC){
return 1;
}
return (alarms & WAN_TE1_FRAMED_ALARMS);
}
/*
******************************************************************************
* sdla_ds_te1_set_status()
*
* Description: Set T1/E1 status. Enable OOF and LCV interrupt (if status
* changed to disconnected.
* Arguments:
* Returns:
******************************************************************************
*/
static void sdla_ds_te1_set_status(sdla_fe_t* fe, unsigned long alarms)
{
sdla_t *card = (sdla_t*)fe->card;
unsigned char curr_fe_status = fe->fe_status;
if (IS_T1_FEMEDIA(fe)){
if (sdla_ds_t1_is_alarm(fe, alarms)){
if (fe->fe_status != FE_DISCONNECTED){
fe->fe_status = FE_DISCONNECTED;
}
}else{
#ifdef WANPIPE_IGNORE_T1_YELLOW
#warning "AFT IGNORING YELLOW ALARM!"
/* If we ignore yellow alarm, we will pass it up
to zaptel. We will be in connected state where
zaptel will be in alarm. Its a deadlock
condition
This option can be compiled using Setup
script in case of some users that
have yellow alarm issues.
Should never be used in ZAPTEL mode!
*/
if (fe->fe_status != FE_CONNECTED){
sdla_ds_te1_clear_alarms(fe, WAN_TE_BIT_YEL_ALARM);
fe->fe_status = FE_CONNECTED;
}
#else
//sdla_ds_te1_clear_alarms(fe, WAN_TE_BIT_YEL_ALARM);
if (!(fe->fe_alarm & WAN_TE_BIT_YEL_ALARM)){
if (fe->fe_status != FE_CONNECTED){
fe->fe_status = FE_CONNECTED;
}
}else{
if (WAN_NET_RATELIMIT()){
DEBUG_EVENT("%s: T1 Waiting for Yellow Alarm to clear...\n",
fe->name);
}
fe->fe_status = FE_DISCONNECTED;
}
#endif
}
} else {
if (sdla_ds_e1_is_alarm(fe, alarms)){
if (fe->fe_status != FE_DISCONNECTED){
fe->fe_status = FE_DISCONNECTED;
}
}else{
if (fe->fe_status != FE_CONNECTED){
fe->fe_status = FE_CONNECTED;
}
}
}
if (curr_fe_status != fe->fe_status){
if (fe->fe_status == FE_CONNECTED){
if (fe->te_param.status_cnt > WAN_TE1_STATUS_THRESHOLD){
DEBUG_EVENT("%s: %s connected!\n",
fe->name,
FE_MEDIA_DECODE(fe));
if (card->wandev.te_report_alarms){
card->wandev.te_report_alarms(
card,
fe->fe_alarm);
}
}else{
if (!fe->te_param.status_cnt){
DEBUG_TEST("%s: %s connecting...\n",
fe->name,
FE_MEDIA_DECODE(fe));
}
fe->te_param.status_cnt ++;
fe->fe_status = FE_DISCONNECTED;
DEBUG_TEST("%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;
fe->te_param.status_cnt = 0;
if (card->wandev.te_report_alarms){
card->wandev.te_report_alarms(card, fe->fe_alarm);
}
}
}else{
fe->te_param.status_cnt = 0;
DEBUG_TEST("%s: %s %s...%d\n",
fe->name,
FE_MEDIA_DECODE(fe),
WAN_FE_STATUS_DECODE(fe),
fe->te_param.status_cnt);
}
#if defined(WAN_FE_SC_DISABLE_INTR)
if (fe->liu_alarm & WAN_TE_BIT_LIU_ALARM_SC){
if (card->wandev.critical_event){
card->wandev.critical_event(card, 0);
}
}
#endif
return;
}
/*
*******************************************************************************
** sdla_te_alarm_print()
**
** Description:
** Arguments:
** Returns:
*/
static int sdla_ds_te1_print_alarms(sdla_fe_t* fe, unsigned int alarms)
{
if (!alarms){
alarms = fe->fe_alarm;
}
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 (%X):\n",
fe->name,
FE_MEDIA_DECODE(fe),
alarms);
if (alarms & WAN_TE_BIT_RAI_ALARM){
DEBUG_EVENT("%s: RAI is ON\n", fe->name);
}
if (alarms & WAN_TE_BIT_LOS_ALARM){
DEBUG_EVENT("%s: LOS is ON\n", fe->name);
}
if (alarms & WAN_TE_BIT_OOF_ALARM){
DEBUG_EVENT("%s: OOF is ON\n", fe->name);
}
if (alarms & WAN_TE_BIT_RED_ALARM){
DEBUG_EVENT("%s: RED is ON\n", fe->name);
}
DEBUG_EVENT("%s: %s LIU Alarms status (%X):\n",
fe->name,
FE_MEDIA_DECODE(fe),
fe->liu_alarm);
if (fe->liu_alarm & WAN_TE_BIT_LIU_ALARM_OC){
DEBUG_EVENT("%s: Open Circuit is detected!\n",
fe->name);
}
if (fe->liu_alarm & WAN_TE_BIT_LIU_ALARM_SC){
DEBUG_EVENT("%s: Short Circuit is detected!\n",
fe->name);
}
if (fe->liu_alarm & WAN_TE_BIT_LIU_ALARM_LOS){
DEBUG_EVENT("%s: Lost of Signal is detected!\n",
fe->name);
}
return 0;
}
/*
*******************************************************************************
** sdla_te_read_alarms()
**
** Description:
** Arguments:
** Returns:
*/
static unsigned int sdla_ds_te1_read_frame_alarms(sdla_fe_t *fe)
{
unsigned int fr_alarm = fe->fe_alarm;
unsigned char rrts1 = READ_REG(REG_RRTS1);
DEBUG_TE1("%s: Framer Alarm status = %02X (%X)\n",
fe->name, rrts1, fr_alarm);
/* Framer alarms */
//if (WAN_FE_FRAME(fe) != WAN_FR_UNFRAMED){
if (rrts1 & BIT_RRTS1_RRAI){
if (!(fr_alarm & WAN_TE_BIT_RAI_ALARM)){
DEBUG_EVENT("%s: RAI alarm is ON\n",
fe->name);
}
fr_alarm |= WAN_TE_BIT_RAI_ALARM;
}else{
if (fr_alarm & WAN_TE_BIT_RAI_ALARM){
DEBUG_EVENT("%s: RAI alarm is OFF\n",
fe->name);
}
fr_alarm &= ~WAN_TE_BIT_RAI_ALARM;
}
//}
if (rrts1 & BIT_RRTS1_RAIS){
if (!(fr_alarm & WAN_TE_BIT_AIS_ALARM)){
DEBUG_EVENT("%s: AIS alarm is ON\n",
fe->name);
}
fr_alarm |= WAN_TE_BIT_AIS_ALARM;
}else{
if (fr_alarm & WAN_TE_BIT_AIS_ALARM){
DEBUG_EVENT("%s: AIS alarm is OFF\n",
fe->name);
}
fr_alarm &= ~WAN_TE_BIT_AIS_ALARM;
}
if (rrts1 & BIT_RRTS1_RLOS){
if (!(fr_alarm & WAN_TE_BIT_LOS_ALARM)){
DEBUG_EVENT("%s: LOS alarm is ON\n",
fe->name);
}
fr_alarm |= WAN_TE_BIT_LOS_ALARM;
}else{
if (fr_alarm & WAN_TE_BIT_LOS_ALARM){
DEBUG_EVENT("%s: LOS alarm is OFF\n",
fe->name);
}
fr_alarm &= ~WAN_TE_BIT_LOS_ALARM;
}
if (WAN_FE_FRAME(fe) != WAN_FR_UNFRAMED){
if (rrts1 & BIT_RRTS1_RLOF){
if (!(fr_alarm & WAN_TE_BIT_OOF_ALARM)){
DEBUG_EVENT("%s: OOF alarm is ON\n",
fe->name);
}
fr_alarm |= WAN_TE_BIT_OOF_ALARM;
}else{
if (fr_alarm & WAN_TE_BIT_OOF_ALARM){
DEBUG_EVENT("%s: OOF alarm is OFF\n",
fe->name);
}
fr_alarm &= ~WAN_TE_BIT_OOF_ALARM;
}
}
/* Aug 30, 2006
** Red alarm is either LOS or OOF alarms */
if (IS_TE_OOF_ALARM(fr_alarm) ||
IS_TE_LOS_ALARM(fr_alarm)){
if (!(fr_alarm & WAN_TE_BIT_RED_ALARM)){
DEBUG_EVENT("%s: RED alarm is ON\n",
fe->name);
}
fr_alarm |= WAN_TE_BIT_RED_ALARM;
}else{
if (fr_alarm & WAN_TE_BIT_RED_ALARM){
DEBUG_EVENT("%s: RED alarm is OFF\n",
fe->name);
}
fr_alarm &= ~WAN_TE_BIT_RED_ALARM;
}
return fr_alarm;
}
static unsigned int sdla_ds_te1_read_liu_alarms(sdla_fe_t *fe)
{
unsigned int alarm = fe->liu_alarm;
unsigned char lrsr = READ_REG(REG_LRSR);
DEBUG_TE1("%s: LIU Alarm status = %02X (%X)\n",
fe->name, lrsr1, alarm);
/* LIU alarms */
if (lrsr & BIT_LRSR_OCS){
if (!(alarm & WAN_TE_BIT_LIU_ALARM_OC)){
DEBUG_EVENT("%s: Open Circuit is detected!\n",
fe->name);
}
alarm |= WAN_TE_BIT_LIU_ALARM_OC;
}else{
if (alarm & WAN_TE_BIT_LIU_ALARM_OC){
DEBUG_EVENT("%s: Open Circuit is cleared!\n",
fe->name);
}
alarm &= ~WAN_TE_BIT_LIU_ALARM_OC;
}
if (lrsr & BIT_LRSR_SCS){
if (!(alarm & WAN_TE_BIT_LIU_ALARM_SC)){
DEBUG_EVENT("%s: Short Circuit is detected!\n",
fe->name);
}
alarm |= WAN_TE_BIT_LIU_ALARM_SC;
}else{
if (alarm & WAN_TE_BIT_LIU_ALARM_SC){
DEBUG_EVENT("%s: Short Circuit is cleared!\n",
fe->name);
}
alarm &= ~WAN_TE_BIT_LIU_ALARM_SC;
}
if (lrsr & BIT_LRSR_LOSS){
if (!(alarm & WAN_TE_BIT_LIU_ALARM_LOS)){
DEBUG_EVENT("%s: Lost of Signal is detected!\n",
fe->name);
}
alarm |= WAN_TE_BIT_LIU_ALARM_LOS;
}else{
if (alarm & WAN_TE_BIT_LIU_ALARM_LOS){
DEBUG_EVENT("%s: Lost of Signal is cleared!\n",
fe->name);
}
alarm &= ~WAN_TE_BIT_LIU_ALARM_LOS;
}
return alarm;
}
static unsigned int sdla_ds_te1_read_alarms(sdla_fe_t *fe, int action)
{
unsigned int fr_alarm = fe->fe_alarm;
unsigned int alarm = fe->liu_alarm;
if (IS_FE_ALARM_READ(action)){
fr_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, fr_alarm);
}
if (IS_FE_ALARM_UPDATE(action)){
fe->fe_alarm = fr_alarm;
fe->liu_alarm = alarm;
}
return fe->fe_alarm;
}
#define WAN_TE_CRIT_ALARM_TIMEOUT 30000 /* 30 sec */
static int sdla_ds_te1_read_crit_alarms(sdla_fe_t *fe)
{
fe->liu_alarm = sdla_ds_te1_read_liu_alarms(fe);
if (fe->liu_alarm & WAN_TE_BIT_LIU_ALARM_SC){
fe->te_param.crit_alarm_start = SYSTEM_TICKS;
}else{
if((SYSTEM_TICKS - fe->te_param.crit_alarm_start) > ((WAN_TE_CRIT_ALARM_TIMEOUT * HZ)/1000)) {
/* 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, unsigned long alarms)
{
if (alarms & WAN_TE_BIT_YEL_ALARM){
DEBUG_TEST("%s: Setting YELLOW alarm (not supported)!\n",
fe->name);
}
return 0;
}
/*
*******************************************************************************
** sdla_ds_te1_clear_alarms()
**
** Description:
** Arguments:
** Returns:
*/
static int sdla_ds_te1_clear_alarms(sdla_fe_t* fe, unsigned long alarms)
{
if (alarms & WAN_TE_BIT_YEL_ALARM){
DEBUG_TEST("%s: Clearing YELLOW alarm (not supported)!\n",
fe->name);
}
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 (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_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_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;
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_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, int type, int 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);
if (!wan_test_bit(TE_CONFIGURED,(void*)&fe->te_param.critical)){
return 0;
}
switch(type){
case WAN_TE_INTR_GLOBAL:
mask = READ_REG(REG_GFIMR);
if (mode == WAN_FE_INTR_ENABLE){
//mask |= (1<<WAN_FE_LINENO(fe));
mask |= (1<<WAN_DS_REGBITMAP(fe));
}else{
//mask &= ~(1<<WAN_FE_LINENO(fe));
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));
//mask |= (1<<WAN_FE_LINENO(fe));
}else{
mask &= ~(1<<WAN_DS_REGBITMAP(fe));
//mask |= (1<<WAN_FE_LINENO(fe));
}
WRITE_REG(REG_GLIMR, mask);
mask = READ_REG(REG_GBIMR);
if (mode == WAN_FE_INTR_ENABLE){
//mask |= (1<<WAN_FE_LINENO(fe));
mask |= (1<<WAN_DS_REGBITMAP(fe));
}else{
//mask &= ~(1<<WAN_FE_LINENO(fe));
mask &= ~(1<<WAN_DS_REGBITMAP(fe));
}
WRITE_REG(REG_GBIMR, mask);
break;
case 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_RIM4, BIT_RIM4_TIMER);*/
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);
}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);
}
break;
case 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_TEST("%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);
break;
case 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);
break;
default:
DEBUG_EVENT("%s: Unsupported interrupt type %X!\n",
fe->name, type);
return -EINVAL;
}
return 0;
}
static int sdla_ds_te1_framer_rx_intr(sdla_fe_t *fe)
{
unsigned char istatus;
istatus = READ_REG(REG_RIIR);
if (istatus & BIT_RIIR_RLS1){
unsigned char rls1 = READ_REG(REG_RLS1);
unsigned char rrts1 = READ_REG(REG_RRTS1);
DEBUG_TE1("%s: RX Latched Status Register 1 %02X\n",
fe->name, rls1);
//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_RAI_ALARM;
DEBUG_EVENT("%s: RAI alarm is ON\n",
fe->name);
}else{
fe->fe_alarm &= ~WAN_TE_BIT_RAI_ALARM;
DEBUG_EVENT("%s: RAI alarm is OFF\n",
fe->name);
}
}
//}
if (rls1 & (BIT_RLS1_RAISC|BIT_RLS1_RAISD)){
if (rrts1 & BIT_RRTS1_RAIS){
fe->fe_alarm |= WAN_TE_BIT_AIS_ALARM;
DEBUG_EVENT("%s: AIS alarm is ON\n",
fe->name);
}else{
fe->fe_alarm &= ~WAN_TE_BIT_AIS_ALARM;
DEBUG_EVENT("%s: AIS alarm is OFF\n",
fe->name);
}
}
if (rls1 & (BIT_RLS1_RLOSC|BIT_RLS1_RLOSD)){
if (rrts1 & BIT_RRTS1_RLOS){
fe->fe_alarm |= WAN_TE_BIT_LOS_ALARM;
DEBUG_EVENT("%s: LOS alarm is ON\n",
fe->name);
}else{
fe->fe_alarm &= ~WAN_TE_BIT_LOS_ALARM;
DEBUG_EVENT("%s: LOS alarm is OFF\n",
fe->name);
}
}
if (WAN_FE_FRAME(fe) != WAN_FR_UNFRAMED){
if (rls1 & (BIT_RLS1_RLOFC|BIT_RLS1_RLOFD)){
if (rrts1 & BIT_RRTS1_RLOF){
fe->fe_alarm |= WAN_TE_BIT_OOF_ALARM;
DEBUG_EVENT("%s: OOF alarm is ON\n",
fe->name);
}else{
fe->fe_alarm &= ~WAN_TE_BIT_OOF_ALARM;
DEBUG_EVENT("%s: OOF alarm is OFF\n",
fe->name);
}
}
}
WRITE_REG(REG_RLS1, rls1);
if (IS_T1_FEMEDIA(fe)){
if (IS_TE_OOF_ALARM(fe->fe_alarm) &&
IS_TE_LOS_ALARM(fe->fe_alarm)){
DEBUG_EVENT("%s: RED alarm is ON\n",
fe->name);
fe->fe_alarm |= WAN_TE_BIT_RED_ALARM;
}else{
DEBUG_EVENT("%s: RED alarm is OFF\n",
fe->name);
fe->fe_alarm &= ~WAN_TE_BIT_RED_ALARM;
}
}
}
if (istatus & BIT_RIIR_RLS2){
unsigned char rls2 = READ_REG(REG_RLS2);
if (IS_E1_FEMEDIA(fe)){
DEBUG_TE1("%s: E1 RX Latched Status Register 2 %02X\n",
fe->name, rls2);
if (rls2 & BIT_RLS2_E1_RSA1){
DEBUG_EVENT(
"%s: Receive Signalling All Ones Event!\n",
fe->name);
}
if (rls2 & BIT_RLS2_E1_RSA0){
DEBUG_EVENT(
"%s: Receive Signalling All Ones Event!\n",
fe->name);
}
if (rls2 & BIT_RLS2_E1_RCMF){
DEBUG_EVENT(
"%s: Receive CRC4 Multiframe Event!\n",
fe->name);
}
if (rls2 & BIT_RLS2_E1_RAF){
DEBUG_EVENT(
"%s: Receive Align Frame Event!\n",
fe->name);
}
}
WRITE_REG(REG_RLS2, rls2);
}
if (istatus & BIT_RIIR_RLS3){
unsigned char rls3 = READ_REG(REG_RLS3);
DEBUG_TE1("%s: RX Latched Status Register 3 %02X\n",
fe->name, rls3);
if (IS_T1_FEMEDIA(fe)){
if (rls3 & BIT_RLS3_T1_LORCC){
DEBUG_EVENT(
"%s: Loss of Receive Clock Condition Clear!\n",
fe->name);
}
if (rls3 & BIT_RLS3_T1_LORCD){
DEBUG_EVENT(
"%s: Loss of Receive Clock Condition Detect!\n",
fe->name);
}
}else{
if (rls3 & BIT_RLS3_E1_LORCC){
DEBUG_EVENT(
"%s: Loss of Receive Clock Condition Clear!\n",
fe->name);
}
if (rls3 & BIT_RLS3_E1_LORCD){
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);
DEBUG_TE1("%s: RX Latched Status Register 4 %02X\n",
fe->name, rls4);
if (rls4 & BIT_RLS4_RSCOS){
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){
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);
DEBUG_TE1("%s: RX Latched Status Register 5 %02X\n",
fe->name, rls5);
if (rls5 & BIT_RLS5_ROVR){
DEBUG_EVENT("%s: Receive FIFO overrun (HDLC)!\n",
fe->name);
}
if (rls5 & BIT_RLS5_RHOBT){
DEBUG_EVENT("%s: Receive HDLC Opening Byte Event (HDLC)!\n",
fe->name);
}
if (rls5 & BIT_RLS5_RPE){
DEBUG_EVENT("%s: Receive Packet End Event (HDLC)!\n",
fe->name);
}
if (rls5 & BIT_RLS5_RPS){
DEBUG_EVENT("%s: Receive Packet Start Event (HDLC)!\n",
fe->name);
}
if (rls5 & BIT_RLS5_RHWMS){
DEBUG_EVENT("%s: Receive FIFO Above High Watermark Set Event (HDLC)!\n",
fe->name);
}
if (rls5 & BIT_RLS5_RNES){
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);
DEBUG_TE1("%s: RX Latched Status Register 7 %02X\n",
fe->name, rls7);
if (rls7 & BIT_RLS7_RRAI_CI){
DEBUG_EVENT("%s: Receive RAI-CI Detect!\n",
fe->name);
}
if (rls7 & BIT_RLS7_RAIS_CI){
DEBUG_EVENT("%s: Receive RAI-CI Detect!\n",
fe->name);
}
if (rls7 & BIT_RLS7_RSLC96){
DEBUG_EVENT("%s: Receive SLC-96 Alignment Event!\n",
fe->name);
}
if (rls7 & BIT_RLS7_RFDLF){
DEBUG_EVENT("%s: Receive FDL Register Full Event!\n",
fe->name);
}
if (rls7 & BIT_RLS7_BC){
DEBUG_EVENT("%s: BOC Clear Event!\n",
fe->name);
}
if (rls7 & BIT_RLS7_BD){
DEBUG_EVENT("%s: BOC Detect Event!\n",
fe->name);
}
WRITE_REG(REG_RLS7, rls7);
}
return 0;
}
static int sdla_ds_te1_framer_tx_intr(sdla_fe_t *fe)
{
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){
DEBUG_EVENT(
"%s: Transmit Pulse Density Violation Event!\n",
fe->name);
}
if (status & BIT_TLS1_LOTCC){
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_bert_intr(sdla_fe_t *fe)
{
unsigned char blsr = READ_REG(REG_BLSR);
if (blsr & BIT_BLSR_BBED){
DEBUG_EVENT("%s: BERT bit error detected!\n",
fe->name);
}
if (blsr & BIT_BLSR_BBCO){
DEBUG_EVENT("%s: BERT Bit Counter overflows!\n",
fe->name);
}
if (blsr & BIT_BLSR_BECO){
DEBUG_EVENT("%s: BERT Error Counter overflows!\n",
fe->name);
}
if (blsr & BIT_BLSR_BRA1){
DEBUG_EVENT("%s: BERT Receive All-Ones Condition!\n",
fe->name);
}
if (blsr & BIT_BLSR_BRA0){
DEBUG_EVENT("%s: BERT Receive All-Zeros Condition!\n",
fe->name);
}
if (blsr & BIT_BLSR_BRLOS){
DEBUG_EVENT("%s: BERT Receive Loss of Synchronization Condition!\n",
fe->name);
}
if (blsr & BIT_BLSR_BSYNC){
DEBUG_EVENT("%s: BERT in synchronization Condition!\n",
fe->name);
}
WRITE_REG(REG_BLSR, blsr);
return 0;
}
static int sdla_ds_te1_liu_intr(sdla_fe_t *fe)
{
unsigned char llsr = READ_REG(REG_LLSR);
unsigned char lrsr = READ_REG(REG_LRSR);
if (llsr & BIT_LLSR_JALTC){
DEBUG_TE1("%s: Jitter Attenuator Limit Trip Clear!\n",
fe->name);
}
if (llsr & BIT_LLSR_JALTS){
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->liu_alarm & WAN_TE_BIT_LIU_ALARM_OC)){
DEBUG_TE1("%s: Open Circuit is detected!\n",
fe->name);
fe->liu_alarm |= WAN_TE_BIT_LIU_ALARM_OC;
}
}else{
if (fe->liu_alarm & WAN_TE_BIT_LIU_ALARM_OC){
DEBUG_TE1("%s: Open Circuit is cleared!\n",
fe->name);
fe->liu_alarm &= ~WAN_TE_BIT_LIU_ALARM_OC;
}
}
}
if (llsr & (BIT_LLSR_SCC | BIT_LLSR_SCD)){
if (lrsr & BIT_LRSR_SCS){
if (!(fe->liu_alarm & WAN_TE_BIT_LIU_ALARM_SC)){
DEBUG_EVENT("%s: Short Circuit is detected!\n",
fe->name);
fe->liu_alarm |= WAN_TE_BIT_LIU_ALARM_SC;
}
}else{
if (fe->liu_alarm & WAN_TE_BIT_LIU_ALARM_SC){
DEBUG_EVENT("%s: Short Circuit is cleared!\n",
fe->name);
fe->liu_alarm &= ~WAN_TE_BIT_LIU_ALARM_SC;
}
}
}
if (llsr & (BIT_LLSR_LOSC | BIT_LLSR_LOSD)){
if (lrsr & BIT_LRSR_LOSS){
if (!(fe->liu_alarm & WAN_TE_BIT_LIU_ALARM_LOS)){
DEBUG_EVENT("%s: Lost of Signal is detected!\n",
fe->name);
fe->liu_alarm |= WAN_TE_BIT_LIU_ALARM_LOS;
}
}else{
if (fe->liu_alarm & WAN_TE_BIT_LIU_ALARM_LOS){
DEBUG_EVENT("%s: Lost of Signal is cleared!\n",
fe->name);
fe->liu_alarm &= ~WAN_TE_BIT_LIU_ALARM_LOS;
}
}
}
WRITE_REG(REG_LLSR, llsr);
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);
framer_istatus = __READ_REG(REG_GFISR);
liu_istatus = __READ_REG(REG_GLISR);
bert_istatus = __READ_REG(REG_GBISR);
framer_imask = __READ_REG(REG_GFIMR);
liu_imask = __READ_REG(REG_GLIMR);
bert_imask = __READ_REG(REG_GBIMR);
//if (framer_istatus & (1 << WAN_FE_LINENO(fe))){
if (framer_istatus & (1 << WAN_DS_REGBITMAP(fe))){
DEBUG_ISR("%s: Interrupt for line %d (framer)\n",
fe->name, WAN_FE_LINENO(fe));
return 1;
}
//if (liu_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;
}
//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;
}
//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)
{
unsigned char status = fe->fe_status;
unsigned char framer_istatus;
unsigned char liu_istatus;
unsigned char bert_istatus;
WAN_ASSERT(fe->write_fe_reg == NULL);
WAN_ASSERT(fe->read_fe_reg == NULL);
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_framer_rx_intr(fe);
sdla_ds_te1_framer_tx_intr(fe);
//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);
//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);
//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->liu_alarm & WAN_TE_BIT_LIU_ALARM_SC){
sdla_fe_timer_event_t event;
/* AL: March 1, 2006: Mask global FE intr */
sdla_ds_te1_intr_ctrl(
fe, 0, WAN_TE_INTR_BASIC, WAN_FE_INTR_MASK, 0x00);
/* Disable automatic update */
sdla_ds_te1_intr_ctrl(
fe, 0, WAN_TE_INTR_PMON, WAN_FE_INTR_MASK, 0x00);
/* Start LINKDOWN poll */
event.type = TE_LINKCRIT_TIMER;
event.delay = POLLING_TE1_TIMER*5;
sdla_ds_te1_add_event(fe, &event);
//if (card->wandev.critical_event){
// card->wandev.critical_event(card, 0);
//}
return 0;
}
#endif
sdla_ds_te1_set_status(fe, fe->fe_alarm);
if (status != fe->fe_status){
if (fe->fe_status != FE_CONNECTED){
sdla_fe_timer_event_t event;
/* AL: March 1, 2006: Mask global FE intr */
sdla_ds_te1_intr_ctrl(
fe, 0,
WAN_TE_INTR_BASIC,
WAN_FE_INTR_MASK,
0x00);
/* Disable automatic update */
sdla_ds_te1_intr_ctrl(
fe, 0,
WAN_TE_INTR_PMON,
WAN_FE_INTR_MASK,
0x00);
/* Start LINKDOWN poll */
event.type = TE_LINKDOWN_TIMER;
event.delay = POLLING_TE1_TIMER*5;
sdla_ds_te1_add_event(fe, &event);
}
}
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;
DEBUG_TEST("[TE1] %s: TE1 timer!\n", fe->name);
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->lock,&smp_flags);
empty = WAN_LIST_EMPTY(&fe->event);
wan_spin_unlock_irq(&fe->lock,&smp_flags);
if (!empty){
if (wan_test_and_set_bit(TE_TIMER_EVENT_PENDING,(void*)&fe->te_param.critical)){
DEBUG_EVENT("%s: RM 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, 1000);
}
return;
}
/*
******************************************************************************
* sdla_ds_te1_add_timer()
*
* Description: Enable software timer interrupt in delay ms.
* Arguments:
* 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)){
return 0;
}
if (wan_test_bit(TE_TIMER_RUNNING,(void*)&fe->te_param.critical)) {
return 0;
}
err = wan_add_timer(&fe->timer, delay * HZ / 1000);
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);
DEBUG_TE1("%s: Add new DS Event=0x%X\n",
fe->name, event->type);
/* 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->lock,&smp_flags);
/* Set event from pending event map */
if (wan_test_and_set_bit(event->type,(void*)&fe->event_map)){
DEBUG_EVENT("%s: WARNING: Event type %d is already pending!\n",
fe->name, event->type);
wan_spin_unlock_irq(&fe->lock, &smp_flags);
wan_free(tevent);
return -EINVAL;
}
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: Internal Error!!!\n", fe->name);
wan_clear_bit(event->type,(void*)&fe->event_map);
wan_spin_unlock_irq(&fe->lock, &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->lock, &smp_flags);
wan_free(tevent);
return -EINVAL;
}
WAN_LIST_INSERT_AFTER(tmp, tevent, next);
}
wan_spin_unlock_irq(&fe->lock, &smp_flags);
return 0;
}
/*
******************************************************************************
* sdla_ds_te1_polling()
*
* Description:
* Arguments:
* Returns:
******************************************************************************
*/
static int sdla_ds_te1_polling(sdla_fe_t* fe)
{
sdla_t *card = (sdla_t*)fe->card;
sdla_fe_timer_event_t *event;
wan_smp_flag_t smp_flags;
u_int8_t pending = 0;
unsigned char value;
unsigned int ch, bit, off;
WAN_ASSERT(fe->write_fe_reg == NULL);
WAN_ASSERT(fe->read_fe_reg == NULL);
#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->lock,&smp_flags);
if (WAN_LIST_EMPTY(&fe->event)){
wan_clear_bit(TE_TIMER_EVENT_PENDING,(void*)&fe->te_param.critical);
wan_spin_unlock_irq(&fe->lock,&smp_flags);
DEBUG_EVENT("%s: WARNING: No FE events in a queue!\n",
fe->name);
sdla_ds_te1_add_timer(fe, HZ);
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->lock,&smp_flags);
DEBUG_TE1("%s: TE1 Polling State=%s Event=%X!\n",
fe->name, WAN_FE_STATUS_DECODE(fe), event->type);
switch(event->type){
case TE_LINKCRIT_TIMER:
if (!sdla_ds_te1_read_crit_alarms(fe)){
event->type = TE_LINKDOWN_TIMER;
}else{
event->type = TE_LINKCRIT_TIMER;
}
event->delay = POLLING_TE1_TIMER;
pending = 1;
break;
case TE_LINKDOWN_TIMER:
sdla_ds_te1_read_alarms(fe, WAN_FE_ALARM_READ|WAN_FE_ALARM_UPDATE);
if (fe->liu_alarm & WAN_TE_BIT_LIU_ALARM_SC){
/* Short circuit detected, go to LINKCRIT state */
event->type = TE_LINKCRIT_TIMER;
event->delay = POLLING_TE1_TIMER;
pending = 1;
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){
event->type = TE_LINKUP_TIMER;
event->delay = POLLING_TE1_TIMER;
pending = 1;
}else{
event->type = TE_LINKDOWN_TIMER;
event->delay = POLLING_TE1_TIMER;
pending = 1;
}
break;
case TE_LINKUP_TIMER:
/* 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){
/* Enable Basic Interrupt */
sdla_ds_te1_intr_ctrl( fe, 0,
WAN_TE_INTR_BASIC,
WAN_FE_INTR_ENABLE,
0x00);
/* Enable automatic update pmon counters */
sdla_ds_te1_intr_ctrl( fe, 0,
WAN_TE_INTR_PMON,
WAN_FE_INTR_ENABLE,
0x00);
if (card->wandev.te_link_state){
card->wandev.te_link_state(card);
}
}else{
event->type = TE_LINKDOWN_TIMER;
event->delay = POLLING_TE1_TIMER;
pending = 1;
}
break;
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:
value = READ_REG(REG_TCR1);
if (IS_T1_FEMEDIA(fe)){
if (event->type == TE_RBS_ENABLE){
value |= BIT_TCR1_T1_TSSE;
}else{
value &= ~BIT_TCR1_T1_TSSE;
}
}else{
if (event->type == TE_RBS_ENABLE){
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, &event->te_event.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 (event->type == TE_RBS_ENABLE){
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);
}
break;
case TE_SET_LB_MODE:
sdla_ds_te1_set_lbmode(fe, event->te_event.lb_type, event->mode);
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);
return -EINVAL;
}
/* Enable interrupts */
sdla_ds_te1_intr_ctrl(fe, 0, WAN_TE_INTR_BASIC, WAN_FE_INTR_ENABLE, 0x00);
/* Enable manual update pmon counter */
sdla_ds_te1_intr_ctrl(fe, 0, WAN_TE_INTR_PMON, WAN_FE_INTR_ENABLE, 0x00);
event->type = TE_LINKDOWN_TIMER;
event->delay = POLLING_TE1_TIMER;
pending = 1;
break;
case TE_POLL_READ:
DEBUG_EVENT("%s: Reading %s Front-End register: Reg[%04X]=%02X\n",
fe->name, FE_MEDIA_DECODE(fe),
event->te_event.reg,
READ_REG(event->te_event.reg));
break;
case TE_POLL_WRITE:
DEBUG_EVENT("%s: Writting %s Front-End register: 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;
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);
/* Add fe timer */
event = WAN_LIST_FIRST(&fe->event);
if (event){
sdla_ds_te1_add_timer(fe, event->delay);
}else{
sdla_ds_te1_add_timer(fe, HZ);
}
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)){
/* E-bit counter (Far End Block Errors) */
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_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 mode)
{
unsigned char value;
WAN_ASSERT(fe->write_fe_reg == NULL);
WAN_ASSERT(fe->read_fe_reg == NULL);
value = READ_REG(REG_LMCR);
if (mode == WAN_TE1_ACTIVATE_LB){
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 mode)
{
unsigned char value;
WAN_ASSERT(fe->write_fe_reg == NULL);
WAN_ASSERT(fe->read_fe_reg == NULL);
value = READ_REG(REG_LMCR);
if (mode == WAN_TE1_ACTIVATE_LB){
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 mode)
{
unsigned char value;
WAN_ASSERT(fe->write_fe_reg == NULL);
WAN_ASSERT(fe->read_fe_reg == NULL);
value = READ_REG(REG_LMCR);
if (mode == WAN_TE1_ACTIVATE_LB){
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 mode)
{
unsigned char value;
WAN_ASSERT(fe->write_fe_reg == NULL);
WAN_ASSERT(fe->read_fe_reg == NULL);
value = READ_REG(REG_RCR3);
if (mode == WAN_TE1_ACTIVATE_LB){
value |= BIT_RCR3_FLB;
}else{
value &= ~BIT_RCR3_FLB;
}
WRITE_REG(REG_LMCR, value);
return 0;
}
/*
******************************************************************************
* sdla_ds_te1_fr_plb()
*
* Description:
* Arguments:
* Returns:
******************************************************************************
*/
static int sdla_ds_te1_fr_plb(sdla_fe_t* fe, unsigned char mode)
{
unsigned char value;
WAN_ASSERT(fe->write_fe_reg == NULL);
WAN_ASSERT(fe->read_fe_reg == NULL);
value = READ_REG(REG_RCR3);
if (mode == WAN_TE1_ACTIVATE_LB){
value |= BIT_RCR3_PLB;
}else{
value &= ~BIT_RCR3_PLB;
}
WRITE_REG(REG_LMCR, value);
return 0;
}
/*
******************************************************************************
* sdla_ds_te1_set_lbmode()
*
* Description:
* Arguments:
* Returns:
******************************************************************************
*/
static int
sdla_ds_te1_set_lbmode(sdla_fe_t *fe, unsigned char type, unsigned char mode)
{
int err = 0;
WAN_ASSERT(fe->write_fe_reg == NULL);
WAN_ASSERT(fe->read_fe_reg == NULL);
DEBUG_EVENT("%s: %s %s mode...\n",
fe->name,
WAN_TE1_LB_MODE_DECODE(mode),
WAN_TE1_LB_TYPE_DECODE(type));
switch(type){
case WAN_TE1_DDLB_MODE:
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_LINELB_MODE:
case WAN_TE1_LIU_RLB_MODE:
err = sdla_ds_te1_liu_rlb(fe, mode);
break;
case WAN_TE1_LIU_DLB_MODE:
if (!sdla_ds_te1_liu_llb(fe, mode)){
err = sdla_ds_te1_liu_rlb(fe, mode);
}
break;
case WAN_TE1_FR_FLB_MODE:
err = sdla_ds_te1_fr_flb(fe, mode);
break;
case WAN_TE1_PAYLB_MODE:
case WAN_TE1_FR_PLB_MODE:
err = sdla_ds_te1_fr_plb(fe, mode);
break;
case WAN_TE1_FR_RLB_MODE:
default:
DEBUG_EVENT("%s: Unsupport loopback mode (%s)!\n",
fe->name,
WAN_TE1_LB_MODE_DECODE(mode));
return -EINVAL;
}
if (!err){
if (mode == WAN_TE1_ACTIVATE_LB){
wan_set_bit(type, &fe->te_param.lb_mode);
}else{
wan_clear_bit(type, &fe->te_param.lb_mode);
}
}
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;
sdla_fe_debug_t *fe_debug;
sdla_fe_timer_event_t event;
int err = 0;
switch(udp_cmd->wan_cmd_command){
case WAN_GET_MEDIA_TYPE:
data[0] = (IS_T1_FEMEDIA(fe) ? WAN_MEDIA_T1 :
IS_E1_FEMEDIA(fe) ? WAN_MEDIA_E1 :
WAN_MEDIA_NONE);
udp_cmd->wan_cmd_return_code = WAN_CMD_OK;
udp_cmd->wan_cmd_data_len = sizeof(unsigned char);
break;
case WAN_FE_SET_LB_MODE:
/* Activate/Deactivate Line Loopback modes */
#if 1
event.type = TE_SET_LB_MODE;
event.te_event.lb_type = data[0]; /* LB type */
event.mode = data[1]; /* LB mode (activate/deactivate) */
event.delay = POLLING_TE1_TIMER;
err = sdla_ds_te1_add_event(fe, &event);
#else
err = sdla_ds_te1_set_lbmode(fe, data[0], data[1]);
#endif
udp_cmd->wan_cmd_return_code =
(!err) ? WAN_CMD_OK : WAN_UDP_FAILED_CMD;
udp_cmd->wan_cmd_data_len = 0x00;
break;
case WAN_FE_GET_STAT:
/* TE1 Update T1/E1 perfomance counters */
sdla_ds_te1_pmon(fe, WAN_FE_PMON_UPDATE|WAN_FE_PMON_READ);
if (udp_cmd->wan_cmd_fe_force){
/* force to read FE alarms */
DEBUG_EVENT("%s: Force to read Front-End alarms\n",
fe->name);
fe->fe_stats.alarms =
sdla_ds_te1_read_alarms(fe, WAN_FE_ALARM_READ|WAN_FE_ALARM_UPDATE);
}
sdla_ds_te1_rxlevel(fe);
memcpy(&data[0], &fe->fe_stats, sizeof(sdla_fe_stats_t));
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_RBS_READ;
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;
case WAN_FE_DEBUG_REG:
event.type = (fe_debug->fe_debug_reg.read) ?
TE_POLL_READ : TE_POLL_WRITE;
event.te_event.reg = fe_debug->fe_debug_reg.reg;
event.te_event.value = fe_debug->fe_debug_reg.value;
event.delay = POLLING_TE1_TIMER;
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_TEST("%s: Enable Transmitter!\n",
fe->name);
udp_cmd->wan_cmd_return_code = WAN_UDP_INVALID_CMD;
break;
case WAN_FE_TXMODE_DISABLE:
DEBUG_TEST("%s: Disable Transmitter (tx tri-state mode)!\n",
fe->name);
udp_cmd->wan_cmd_return_code = WAN_UDP_INVALID_CMD;
break;
default:
udp_cmd->wan_cmd_return_code = WAN_UDP_INVALID_CMD;
udp_cmd->wan_cmd_data_len = 0;
break;
}
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_ALOS_ALARM(fe->fe_alarm),
"LOS", WAN_TE_LOS_ALARM(fe->fe_alarm));
PROC_ADD_LINE(m,
PROC_STATS_ALARM_FORMAT,
"RED", WAN_TE_RED_ALARM(fe->fe_alarm),
"AIS", WAN_TE_AIS_ALARM(fe->fe_alarm));
if (IS_T1_FEMEDIA(fe)){
PROC_ADD_LINE(m,
PROC_STATS_ALARM_FORMAT,
"YEL", WAN_TE_YEL_ALARM(fe->fe_alarm),
"OOF", WAN_TE_OOF_ALARM(fe->fe_alarm));
}else{
PROC_ADD_LINE(m,
PROC_STATS_ALARM_FORMAT,
"OOF", WAN_TE_OOF_ALARM(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;
}