/*********************************************************************** | |
* Copyright (C) 2001, ZTE Corporation. | |
* | |
* File Name: si_adt.c | |
* File Mark: | |
* Description: siliconlab lib adapter. | |
* History : | |
* Date : 2010-04-07 | |
* Version :1.0 | |
* Author : duanzhw 182073 | |
* Modification: | |
**********************************************************************/ | |
#include <linux/module.h> | |
#include <linux/kernel.h> | |
#include <linux/timer.h> | |
#include <linux/fs.h> | |
#include <linux/sched.h> | |
#include <linux/wait.h> | |
#include <linux/init.h> | |
#include <linux/fcntl.h> | |
#include <linux/list.h> | |
#include <linux/slab.h> | |
#include <linux/signal.h> | |
//#include <linux/smp_lock.h> | |
#include <asm/uaccess.h> | |
#include <linux/delay.h> | |
#include "si_voice_datatypes.h" | |
#include "proslic_mlt.h" | |
#include "proslic_mlt_math.h" | |
#include "timer_adt.h" | |
#ifdef SI3217X | |
#include "si3217x.h" | |
#include "si3217x_constants.h" | |
#endif | |
#ifdef SI3218X | |
#include "si3218x.h" | |
#include "si3218x_constants.h" | |
#endif | |
#include "112.h" | |
#include "usr_line.h" | |
//#include "generic-ability.h" | |
/**************************port map****************************/ | |
static USL_PORT_MAP port_map[MAX_PORT_NUM] = { | |
/*flg, cs , chan, port , type, tx, rx*/ | |
{0, 0, 0, 0, 0, 0, 0} | |
// {0, 0, 0, 0, 0, 1, 1}, | |
// {0, 0, 0, 0, 0, 2, 2}, | |
// {0, 0, 0, 0, 0, 3, 3}, | |
}; | |
/**************************************************************/ | |
ctrl_S spiGciObj[MAX_PORT_NUM]; /* User¡¯s control interface object, can be consider as the port number */ | |
systemTimer_S timerObj; /* User¡¯s timer object */ | |
controlInterfaceType *ProHWIntf[MAX_PORT_NUM]; | |
/* Define array of ProSLIC device objects */ | |
ProslicDeviceType *ProSLICDevices[MAX_PORT_NUM]; | |
/* Define array of ProSLIC channel object pointers */ | |
proslicChanType_ptr arrayOfProslicChans[MAX_PORT_NUM]; | |
/* 112 test */ | |
//ProSLICMLTType SLICMLT; | |
//ProSLIC_mlt_foreign_voltages_state vState; | |
//ProSLIC_mlt_rmeas_state rMeas; | |
//ProSLIC_mlt_capacitance_state CapState; | |
//ProSLIC_mlt_ren_state RenState; | |
long RingVol[MAX_RING_CNT]= {0}, RingCnt = 0; | |
//TestResult_t ResBuf; | |
/* board cfg */ | |
static SILAB_CFG_CHIP_t BoardCfg[MAX_PORT_NUM] = {{0}}; | |
/* As for one board, using one signal to avoid the conflict */ | |
static const u8 pcmcfg[] = {0x4,0x1,0x3}; | |
static Port_t ports[MAX_PORT_NUM]; | |
//extern u8 init_flg; | |
extern slic_state current_state; | |
extern USL_PORT *pstUslPort; | |
extern int dtmf_mute; | |
extern u8 slic_offhook; | |
static s8 si_signal_ctrl(Port_t *pPort, const void *signal_attr,const u8 flag); | |
static s8 si_timeslot_set(Port_t *pPort, const u8 TxTs, const u8 RxTs); | |
static s8 si_timeslot_release(Port_t *pPort); | |
static s8 si_chip_reset(Port_t *pPort, u16 port); | |
static s8 si_polarity_reverse(Port_t *pPort, const u16 port); | |
static s8 si_parm_set(Port_t *pPort, u8 *parm, const u8 size); | |
static s8 si_parm_get(Port_t *pPort, u8 *parm, const u8 size ); | |
static s8 si_ram_set(Port_t *pPort, u8 *parm, const u8 size); | |
static s8 si_ram_get(Port_t *pPort, u8 *parm, const u8 size ); | |
static s8 si_time_cfg(Port_t *pPort, const USL_CONFIG *Slc_Time_Cfg); | |
static s8 si_slctool_time_cfg(Port_t *pPort, SLIC_IOCTL_CMD cmd, u16 wTime); | |
static s8 si_time_print(Port_t *pPort); | |
static s8 si_dial_set(Port_t *pPort, u8 bDialEn); | |
static s8 si_electric_set(Port_t *pPort, const u16 port, const ELECTRIC_CFG_CUSTOMIZED *buf); | |
static s8 si_start_test(Port_t *pPort, const WriteCmd_t *Cmd); | |
static s8 si_stop_test(Port_t *pPort ); | |
static s8 si_read_result(Port_t *pPort, TestResult_t *pstResult); | |
static void ScanSiBoard(USL_PORT *pUslPort); | |
static void StartSiLineTest(Port_t *pPort, uInt8 TestId); | |
static s8 StartLineConnectTest(Port_t *pPort); | |
static void SiScanSignals(USL_PORT *usl_port, u8 hook); | |
static void SiUpdatePort(Port_t *data, u16 port, u8 event); | |
static s8 si_update_dcpara(SILAB_CFG_CHIP_t *ptOldCfg, u8 vol_param, u8 cur_param); | |
static s8 si_update_ringpara(SILAB_CFG_CHIP_t *ptOldCfg, u8 ringvol_param); | |
static int setUserMode (proslicChanType_ptr hProslic, BOOLEAN on); | |
USL_PORT_MAP *get_port_item(u8 port, u8 type); | |
int InitSiliconBoard(void); | |
int SiRemoveBoard(void); | |
void InitSiliconChip(Port_t *pPort); | |
int SiSetSemaphore(void *pHCtrl, int s); | |
int ProSLIC_PCMEnable(proslicChanType_ptr hProslic, u8 enable); | |
int ProSLIC_GetLinefeedStatus (proslicChanType_ptr hProslic, uInt8 *pLinefeed); | |
int VerifyChipID(ctrl_S *hCtrl, u8 chan); | |
void MLTClearSettings(ProSLICMLTType *pProSLICMLT); | |
void MLTClearResults(ProSLICMLTType *pProSLICMLT); | |
void SiMltScan(Port_t *pPort); | |
void SiSendResultVol(Port_t *pPort, ProSLICMLTType *pMlt); | |
void SiSendResultCap(Port_t *pPort, ProSLICMLTType *pMlt); | |
void SiSendResultRes(Port_t *pPort, ProSLICMLTType *pMlt); | |
void SiSendResultDCFeedSt(Port_t *pPort); | |
void SiSendResultBatteryVol(Port_t *pPort); | |
void SiSendResultRingtouser(Port_t *pPort); | |
void SiRen(Port_t *pPort, ProSLICMLTType *pMlt); | |
void SiSendResultHook(Port_t *pPort); | |
long ChangeData(unsigned long n); | |
long lldivde(long long x, long y); | |
long longfabs(long x); | |
#define FSK_DEPTH_TRIG 4 | |
#define DISABLE_FSK_CID | |
//extern int spi_chipid_get(u8 port, u8 *cs, u8 *ch); | |
//extern const s8 *board_type_acquire(u32 *type); | |
/***************************************************************************/ | |
static CODEC_OPS si_ops = { | |
.codec_signal_ctrl = si_signal_ctrl, | |
.codec_timeslot_set = si_timeslot_set, | |
.codec_timeslot_release = si_timeslot_release, | |
.codec_reset = si_chip_reset, | |
.codec_polarity_reverse = si_polarity_reverse, | |
.codec_parm_cfg = si_parm_set, | |
.codec_parm_get = si_parm_get, | |
.codec_ram_cfg = si_ram_set, | |
.codec_ram_get = si_ram_get, | |
.codec_time_cfg = si_time_cfg, | |
.codec_slctool_time_cfg = si_slctool_time_cfg, | |
.codec_time_print = si_time_print, | |
.codec_dial_set = si_dial_set, | |
.codec_electric_cfg = si_electric_set, | |
.codec_start_test = si_start_test, | |
.codec_stop_test = si_stop_test, | |
.codec_read_reslult = si_read_result, | |
.codec_scan = ScanSiBoard, | |
}; | |
/****************** public func *******************/ | |
USL_PORT_MAP * get_port_item(u8 port, u8 type) | |
{ | |
u8 i = 0; | |
for( i = 0; i < MAX_PORT_NUM; i++ ) | |
{ | |
if( port_map[i].flg == 0 ) continue; | |
if( port == port_map[i].port && type == port_map[i].type ) | |
{ | |
return &port_map[i]; | |
} | |
} | |
return NULL; | |
} | |
void make_port_map(void) | |
{ | |
u8 cs = 0, chan = 0; | |
u8 i = 0; | |
int ret = 0; | |
for( i = 0; i < MAX_PORT_NUM; i++ ) | |
{ | |
//ret = spi_chipid_get(i, &cs, &chan); | |
if( 0 == ret ) | |
{ | |
#ifdef DEBUG_SLIC_ON | |
USLPUT0("Find a port:%d with chan %d cs %d\n", i, chan, cs); | |
#endif | |
port_map[i].flg = 1; | |
port_map[i].cs = cs; | |
port_map[i].chan = chan; | |
port_map[i].port = i; | |
port_map[i].type = SLIC_PORT_TYPE; | |
port_map[i].tx = i; | |
port_map[i].rx = i; | |
} | |
else | |
{ | |
#ifdef DEBUG_SLIC_ON | |
USLPUT0("cann't Find a port:%d\n", i); | |
#endif | |
port_map[i].flg = 0; | |
} | |
} | |
} | |
void SlicCfgParaBasedBoardType(void) | |
{ | |
//u32 dwBoardType = 0; | |
u32 dwPort = 0; | |
//board_type_acquire(&dwBoardType); | |
for (dwPort=0; dwPort<MAX_PORT_NUM; dwPort++) | |
{ | |
#ifdef SI3217X | |
/*switch(dwBoardType) | |
{ | |
default: | |
USLPUT0("Board default NO PTC\n");*/ | |
BoardCfg[dwPort].ePTC = NOPTC; | |
// break; | |
//} | |
//#if defined (SILAB_SUPPORT_BUCKBOOST) | |
// BoardCfg[dwPort].generel_cfg = 0; | |
//#elif defined (SILAB_SUPPORT_LCQC) | |
// BoardCfg[dwPort].generel_cfg = 3; | |
//#else | |
BoardCfg[dwPort].generel_cfg = 2; | |
//#endif | |
BoardCfg[dwPort].ring = RING_F20_45VRMS_0VDC_LPR_SHORTTIME;//RING_F20_45VRMS_0VDC_LPR; | |
BoardCfg[dwPort].dc = DCFEED_48V_20MA; | |
BoardCfg[dwPort].tone = TONEGEN_FCC_DIAL; | |
BoardCfg[dwPort].Impe = ZSYN_600_0_0_30_0; | |
BoardCfg[dwPort].meter = DEFAULT_PULSE_METERING; | |
BoardCfg[dwPort].bLineOpen100msEn = 0; | |
BoardCfg[dwPort].bDisablePowerSave = 0; | |
BoardCfg[dwPort].a_u_law = PCM_16LIN; | |
BoardCfg[dwPort].cid = ITU_FSK; | |
BoardCfg[dwPort].linestaus = LF_FWD_ACTIVE; | |
BoardCfg[dwPort].wide = 2; | |
BoardCfg[dwPort].offset = 1; | |
BoardCfg[dwPort].rxgain = 0; | |
BoardCfg[dwPort].txgain = 0; | |
#endif | |
#ifdef SI3218X | |
BoardCfg[dwPort].ePTC = NOPTC; | |
BoardCfg[dwPort].generel_cfg = 0; | |
BoardCfg[dwPort].ring = RING_F20_45VRMS_0VDC_LPR;//RING_F20_45VRMS_0VDC_LPR;RING_F20_45VRMS_0VDC_LPR_SHORTTIME | |
BoardCfg[dwPort].dc = DCFEED_48V_20MA; | |
BoardCfg[dwPort].tone = TONEGEN_FCC_DIAL; | |
BoardCfg[dwPort].Impe = ZSYN_600_0_0_30_0; | |
BoardCfg[dwPort].meter = DEFAULT_PULSE_METERING; | |
BoardCfg[dwPort].bLineOpen100msEn = 0; | |
BoardCfg[dwPort].bDisablePowerSave = 0; | |
BoardCfg[dwPort].a_u_law = PCM_16LIN; | |
BoardCfg[dwPort].cid = ITU_FSK; | |
BoardCfg[dwPort].linestaus = LF_FWD_ACTIVE; | |
BoardCfg[dwPort].wide = 2; | |
BoardCfg[dwPort].offset = 1; | |
BoardCfg[dwPort].rxgain = 0; | |
BoardCfg[dwPort].txgain = 0; | |
#endif | |
} | |
return; | |
} | |
int InitSlicChip(void) | |
{ | |
int ret = 0; | |
make_port_map(); | |
ret = InitSiliconBoard(); | |
return ret; | |
} | |
void DeinitSlicChip(void) | |
{ | |
SiRemoveBoard(); | |
return; | |
} | |
void SendErrorTest(Port_t *pPort, int err) | |
{ | |
USLPUT2(" Test Error %d.\n", err ); | |
pPort->stLineTestPara.pstResult->flg = TEST_ERROR; | |
pPort->stLineTestPara.pstResult->err_num = err; /*´íÎóºÅ*/ | |
usrline_report(pPort->stLineTestPara.pstResult->port, EV_FXS_TEST_DONE, 0, 0); | |
return; | |
} | |
void slic_inf_precfg(SLCINF_CFG *ptCfg) | |
{ | |
if (NULL == ptCfg) | |
{ | |
USLPUT0("%s ptCfg NULL \n", __FUNCTION__); | |
return; | |
} | |
if (ptCfg->bPort >= MAX_PORT_NUM) | |
{ | |
USLPUT0("%s port:%d is bigger than MAX_PORT_NUM:%d\n", __FUNCTION__, ptCfg->bPort, MAX_PORT_NUM); | |
return; | |
} | |
si_update_dcpara(&BoardCfg[ptCfg->bPort], ptCfg->bCusDcVol, ptCfg->bCusDcLoopCurr); | |
si_update_ringpara(&BoardCfg[ptCfg->bPort], ptCfg->bCusRingVpk); | |
BoardCfg[ptCfg->bPort].bLineOpen100msEn = ptCfg->bLineOpen100msEn; | |
BoardCfg[ptCfg->bPort].bDisablePowerSave = ptCfg->bDisablePowerSave; | |
switch(ptCfg->dwImpe) | |
{ | |
#if 0 | |
case 600: | |
BoardCfg[ptCfg->bPort].Impe = ZSYN_600+BoardCfg[ptCfg->bPort].ePTC; | |
break; | |
case 680: | |
BoardCfg[ptCfg->bPort].Impe = ZSYN_200_680+BoardCfg[ptCfg->bPort].ePTC; | |
break; | |
#endif | |
default: | |
BoardCfg[ptCfg->bPort].Impe = ZSYN_600_0_0_30_0; | |
break; | |
} | |
BoardCfg[ptCfg->bPort].rxgain = ptCfg->i32Rxgain; | |
BoardCfg[ptCfg->bPort].txgain = ptCfg->i32Txgain; | |
USLPUT3("port:%d Dc:%d U:%d A:%d Ring:%d VPK:%d 100msEn:%d, DisPowerSave:%d impe:%d ePTC:%d dwImpe:%d rxgain(D-A):%d, txgain(A-D):%d\n", | |
ptCfg->bPort, | |
BoardCfg[ptCfg->bPort].dc, ptCfg->bCusDcVol, ptCfg->bCusDcLoopCurr, | |
BoardCfg[ptCfg->bPort].ring, ptCfg->bCusRingVpk, | |
BoardCfg[ptCfg->bPort].bLineOpen100msEn, BoardCfg[ptCfg->bPort].bDisablePowerSave, | |
BoardCfg[ptCfg->bPort].Impe, BoardCfg[ptCfg->bPort].ePTC, ptCfg->dwImpe, | |
BoardCfg[ptCfg->bPort].rxgain, BoardCfg[ptCfg->bPort].txgain); | |
return; | |
} | |
/****************** end *******************/ | |
/****************** func for si_ops ****************/ | |
static void si_tone_init(Port_t *pPort, SIGNAL_DATA *signal_attr) | |
{ | |
u8 bToneIndex = signal_attr->tone_type; | |
u8 bOscillator2En = 0; | |
/* modified by zhanghuan for new SIGNAL_DATA struct */ | |
#if 0 | |
if (0 != signal_attr->cadence[0].freq2) | |
{ | |
bOscillator2En = 1; | |
} | |
switch(signal_attr->cadence[0].freq1) | |
{ | |
default: | |
bToneIndex = TONEGEN_450_N18DB_350_N18DB; | |
break; | |
} | |
#endif | |
/* modified by zhanghuan for new SIGNAL_DATA struct */ | |
/*use preset tone type */ | |
printk("ProSLIC_ToneGenSetup %d \n", bToneIndex); | |
ProSLIC_ToneGenSetup(pPort->ProObj, bToneIndex); | |
return; | |
} | |
uInt8 checkSum(char *str) | |
{ | |
int i=0; | |
uInt8 sum = 0; | |
while(str[i] != 0) | |
{ | |
sum += str[i++]; | |
} | |
return -sum; | |
} | |
/*****************************************************************************************************/ | |
/* Wait for FSK buffer to be available... */ | |
void waitForCIDDone(SiVoiceChanType_ptr pChan) | |
{ | |
int tmp = 0; | |
do | |
{ | |
ProSLIC_CheckCIDBuffer(pChan, &tmp); | |
} | |
while(tmp == 0); | |
} | |
void sendFSKData(proslicChanType_ptr hProslic, char *stream, int preamble_enable) | |
{ | |
uInt8 csum; | |
int buff_timeout; | |
int cid_remainder; | |
int baud_rate = 1200; | |
int bits = 10; /* 1 start + 8 data + 1 stop */ | |
int i; | |
const uInt8 cid_preamble[] = {'U','U','U','U','U','U','U','U'}; | |
buff_timeout = ((8 - FSK_DEPTH_TRIG) * (10000*bits)/baud_rate)/10; | |
/* | |
** SEND CID HERE | |
*/ | |
/* Clear FSK buffer */ | |
if((stream[1]+3)%FSK_DEPTH_TRIG) | |
{ | |
cid_remainder = 1; | |
} | |
else | |
{ | |
cid_remainder = 0; | |
} | |
ProSLIC_EnableCID(hProslic); | |
msleep(133); /* > 130ms of mark bits */ | |
/* Enable FSKBUF interrupt so we can check it later. */ | |
SiVoice_WriteReg(hProslic,PROSLIC_REG_IRQEN1,0x40); | |
(void)SiVoice_ReadReg(hProslic, | |
PROSLIC_REG_IRQ1); /* Clear IRQ1 */ | |
printk("howard fsk cid send preamble\n"); | |
if(preamble_enable) | |
{ | |
/* Send preamble */ | |
for(i=0; i<30; i+=FSK_DEPTH_TRIG) | |
{ | |
if(i >= 8) /* The FIFO depth is 8 bytes, start waiting for it to empty */ | |
{ | |
waitForCIDDone(hProslic); | |
} | |
ProSLIC_SendCID(hProslic,cid_preamble,FSK_DEPTH_TRIG); | |
} | |
if (30%FSK_DEPTH_TRIG) | |
{ | |
waitForCIDDone(hProslic); | |
} | |
ProSLIC_SendCID(hProslic,cid_preamble,30%FSK_DEPTH_TRIG); | |
waitForCIDDone(hProslic); | |
/* Delay > 130ms for idle mark bits */ | |
msleep(133); | |
} | |
/* Send Message */ | |
printk("howard fsk cid send message\n"); | |
csum = checkSum(stream); | |
stream[stream[1]+2] = csum; | |
for(i=0; i<(stream[1]+3); i+=FSK_DEPTH_TRIG) | |
{ | |
if(i>=8) | |
{ | |
waitForCIDDone(hProslic); | |
} | |
ProSLIC_SendCID(hProslic,&(stream[i]),FSK_DEPTH_TRIG); | |
} | |
if(cid_remainder) | |
{ | |
waitForCIDDone(hProslic); | |
ProSLIC_SendCID(hProslic, | |
&(stream[((stream[1]+3)/FSK_DEPTH_TRIG)*FSK_DEPTH_TRIG]), | |
(stream[1]+3)%FSK_DEPTH_TRIG); | |
} | |
waitForCIDDone(hProslic); | |
/* Make sure the last byte is shifted out prior to disabling CID */ | |
msleep(buff_timeout); | |
ProSLIC_DisableCID(hProslic); | |
} | |
/*****************************************************************************************************/ | |
/* | |
** Sequential (blocking) example of CID transmission | |
*/ | |
void sendCIDStream(proslicChanType_ptr hProslic) | |
{ | |
char cid_msg[] = | |
"\x80" /* MDMF Type */ | |
"\x27" /* Message Length */ | |
"\x01" /* Date/Time Param */ | |
"\x08" /* 8-byte Date/Time */ | |
"07040815" /* July 4th 08:15 am */ | |
"\x02" /* Calling Number Param */ | |
"\x0A" /* 10-byte Calling Number */ | |
"5124168500" /* Phone Number */ | |
"\x07" /* Calling Name Param */ | |
"\x0F" /* 15-byte Calling Name */ | |
"Nice" /* Calling Name */ | |
"\x20" /* Calling Name (whitespace) */ | |
"ProSLIC!!!" /* Calling Name */ | |
"\x00" /* Placeholder for Checksum */ | |
"\x00" /* Markout */ | |
; | |
uInt8 reg_tmp; | |
ProSLIC_FSKSetup(hProslic,0); | |
ProSLIC_RingSetup(hProslic,1); | |
reg_tmp =SiVoice_ReadReg(hProslic,PROSLIC_REG_RINGCON); | |
SiVoice_WriteReg(hProslic,PROSLIC_REG_RINGCON,reg_tmp&0xF0); | |
/* Ensure OFFHOOK Active */ | |
//ProSLIC_SetLinefeedStatus(hProslic,LF_FWD_ACTIVE); | |
//msleep(500); | |
/* 1st Ring Burst */ | |
ProSLIC_SetLinefeedStatus(hProslic,LF_RINGING); | |
msleep(2500); | |
/* OHT - the alternative is to have the configuration for ringing set OHT mode automatically... */ | |
//ProSLIC_SetLinefeedStatus(hProslic,LF_FWD_OHT); /* no need if RINGCON is set to 0x58*/ | |
//msleep(500); /* Delay 250 to 3600ms */ | |
sendFSKData(hProslic, cid_msg, 1); | |
} | |
static s8 si_signal_ctrl(Port_t *pPort, const void *signal_attr,const u8 flag) | |
{ | |
static unsigned long int jiffies_save; | |
int ret = -1; | |
if(NULL == pPort) | |
{ | |
USLPUT0("si_signal_ctrl pPort NULL \n"); | |
return -1; | |
} | |
switch(flag) | |
{ | |
/* play ring */ | |
case RING_SIGNAL_INIT: | |
jiffies_save = jiffies; | |
USLPUT3("RING_SIGNAL_INIT\n"); | |
break; | |
case RING_SIGNAL_ON: | |
//printk("start play ring ProSLIC_Init_MultiBOM\n"); | |
//ProSLIC_Init_MultiBOM(&(pPort->ProObj),1,3); | |
/* ring and cid is moved to ioctl */ | |
#if 0 | |
printk("start play ring\n"); | |
#ifdef DISABLE_FSK_CID | |
pPort->ProObj->channelType = PROSLIC; | |
ret = ProSLIC_SetLinefeedStatus( pPort->ProObj, LF_RINGING); | |
USLPUT3("RING_SIGNAL_ON %lu, ret %d\n", jiffies - jiffies_save, ret); | |
jiffies_save = jiffies; | |
#else | |
/* add by zhanghuan for FSK CID */ | |
sendCIDStream(pPort->ProObj); | |
#endif | |
current_state = RINGING; | |
#endif | |
break; | |
case RING_SIGNAL_OFF: | |
ProSLIC_SetLinefeedStatus( pPort->ProObj, LF_FWD_OHT); | |
USLPUT3("RING_SIGNAL_OFF %lu\n", jiffies - jiffies_save); | |
jiffies_save = jiffies; | |
current_state = NONE; | |
break; | |
case RING_SIGNAL_OFF_REVERSED: | |
ProSLIC_SetLinefeedStatus( pPort->ProObj, LF_REV_OHT); | |
USLPUT3("RING_SIGNAL_OFF_REVERSED %lu\n", jiffies - jiffies_save); | |
jiffies_save = jiffies; | |
break; | |
case RING_SIGNAL_CLEAN_OFF: | |
case RING_SIGNAL_CLEAN_ON: | |
ProSLIC_SetLinefeedStatus( pPort->ProObj, LF_FWD_ACTIVE); | |
USLPUT3("RING_SIGNAL_CLEAN_ON %lu\n", jiffies - jiffies_save); | |
jiffies_save = jiffies; | |
current_state = NONE; | |
break; | |
/* play tone */ | |
case TONE_SIGNAL_INIT: | |
ProSLIC_ToneGenStop(pPort->ProObj); | |
current_state = NONE; | |
si_tone_init(pPort, (SIGNAL_DATA *)signal_attr); | |
break; | |
case TONE_SIGNAL_ON: | |
printk("start play tone\n"); | |
if(TONE_DIAL != ((SIGNAL_DATA *)signal_attr)->tone_type) | |
{ | |
ProSLIC_ToneGenStart(pPort->ProObj, 1); // Only DIAL TONE play continusely | |
} | |
else | |
{ | |
ProSLIC_ToneGenStart(pPort->ProObj, 0); | |
} | |
current_state = PLAYING_TONE; | |
break; | |
case TONE_SIGNAL_OFF: | |
ProSLIC_ToneGenStop(pPort->ProObj); | |
current_state = NONE; | |
break; | |
case TONE_SIGNAL_CLEAN: | |
ProSLIC_ToneGenStop(pPort->ProObj); | |
current_state = NONE; | |
break; | |
default: | |
break; | |
} | |
return 0; | |
} | |
static s8 si_timeslot_set(Port_t *pPort, const u8 TxTs, const u8 RxTs) | |
{ | |
u16 tx = 0; | |
u16 rx = 0; | |
if( NULL == pPort ) | |
{ | |
USLPUT0("leg_timeslot_set pPort NULL \n"); | |
return -1; | |
} | |
tx = TxTs * 8 * pPort->pPreCfg->wide + pPort->pPreCfg->offset; | |
rx = RxTs * 8 * pPort->pPreCfg->wide + pPort->pPreCfg->offset; | |
USLPUT2("si_timeslot_set tx %d rx %d. \n",tx,rx); | |
ProSLIC_PCMTimeSlotSetup( pPort->ProObj, rx , tx ); | |
ProSLIC_PCMEnable( pPort->ProObj, 1); | |
return 0; | |
} | |
static s8 si_timeslot_release(Port_t *pPort) | |
{ | |
if( NULL == pPort ) | |
{ | |
USLPUT0("si_timeslot_release line NULL \n"); | |
return -1; | |
} | |
ProSLIC_PCMEnable( pPort->ProObj, 0); | |
ProSLIC_PCMTimeSlotSetup( pPort->ProObj, MAX_PORT_NUM * 8 , MAX_PORT_NUM * 8 ); | |
return 0; | |
} | |
static s8 si_chip_reset(Port_t *pPort, u16 port) | |
{ | |
if( NULL == pPort ) | |
{ | |
USLPUT0("si_chip_reset pPort NULL \n"); | |
return -1; | |
} | |
if( HOOKOFF == pPort->hook_state ) | |
{ | |
ProSLIC_SetLinefeedStatus(pPort->ProObj, LF_FWD_ACTIVE); | |
USLPUT3("ProSLIC_SetLinefeedStatus %d LF_FWD_ACTIVE\n",port); | |
usrline_report(port, EV_FXS_HOOKON, 0 , 0); | |
} | |
pPort->hook_state = HOOKON; | |
pPort->pulse_dig = 0; | |
pPort->stLineTestPara.si_item = 0xff; | |
pPort->stLineTestPara.test_flg = NOT_TEST; | |
pPort->stLineTestPara.cnt = 0; | |
pPort->low_len = 0; | |
pPort->high_len = 0; | |
pPort->bDialEn = EV_DIAL_STOP; | |
return 0; | |
} | |
static s8 si_polarity_reverse(Port_t *pPort, const u16 port) | |
{ | |
u8 state = 0; | |
u8 new_state = 0; | |
if( NULL == pPort ) | |
{ | |
USLPUT0("si_polarity_reverse pPort NULL \n"); | |
return -1; | |
} | |
ProSLIC_GetLinefeedStatus(pPort->ProObj, &state); | |
switch(state) | |
{ | |
case LF_REV_ACTIVE: | |
case LF_FWD_ACTIVE: | |
case LF_FWD_OHT: | |
case LF_REV_OHT: | |
new_state = state ^ 0x4 ; | |
break; | |
default: | |
USLPUT0("reverse error at state% d\n",state); | |
return -1; | |
} | |
if((1 == pPort->pPreCfg->bLineOpen100msEn)&& (LF_REV_ACTIVE == state)) | |
{ | |
ProSLIC_SetLinefeedStatus(pPort->ProObj, LF_OPEN); | |
msleep(100); | |
USLPUT2("SLIC set line feed status from OPEN to %d\n",new_state); | |
} | |
ProSLIC_SetLinefeedStatus( pPort->ProObj, new_state ); | |
return 0; | |
} | |
static s8 si_parm_set( Port_t *pPort, u8 *parm, const u8 size) | |
{ | |
if( NULL == pPort ) | |
{ | |
USLPUT0("si_parm_set pPort NULL \n"); | |
return -1; | |
} | |
ctrl_WriteRegisterWrapper( pPort->ProObj->deviceId->ctrlInterface->hCtrl, pPort->ProObj->channel,parm[0],parm[1]); | |
return 0; | |
} | |
static s8 si_parm_get( Port_t *pPort, u8 *parm, const u8 size ) | |
{ | |
u8 addr = 0; | |
if( NULL == pPort ) | |
{ | |
USLPUT0("si_parm_get pPort NULL \n"); | |
return -1; | |
} | |
addr = parm[0]; | |
*parm = ctrl_ReadRegisterWrapper( pPort->ProObj->deviceId->ctrlInterface->hCtrl, pPort->ProObj->channel, addr); | |
USLPUT3("addr %d, data 0x%x\n", addr, parm[0]); | |
return 0; | |
} | |
static s8 si_ram_set( Port_t *pPort, u8 *parm, const u8 size) | |
{ | |
u8 *temp_p = NULL; | |
u32 ram = 0; | |
u32 write_value = 0; | |
u32 read_value = 0; | |
if((NULL == pPort) || (NULL == parm)) | |
{ | |
USLPUT0("si_ram_set pPort/parm NULL \n"); | |
return -1; | |
} | |
temp_p = (u8*) parm; | |
ram = *temp_p & 0xff; | |
temp_p++; | |
ram = ram | ((u8)(*temp_p)<<8); | |
temp_p++; | |
write_value = *temp_p; | |
temp_p++; | |
write_value = write_value | ((u8)(*temp_p)<<8); | |
temp_p++; | |
write_value = write_value | ((u8)(*temp_p)<<16); | |
temp_p++; | |
write_value = write_value | ((u8)(*temp_p)<<24); | |
USLPUT3("write: ram:%d value:0x%x.\n", ram, write_value); | |
setUserMode(pPort->ProObj, TRUE); | |
ctrl_WriteRAMWrapper (pPort->ProObj->deviceId->ctrlInterface->hCtrl, pPort->ProObj->channel, ram, write_value); | |
read_value = ctrl_ReadRAMWrapper(pPort->ProObj->deviceId->ctrlInterface->hCtrl, pPort->ProObj->channel, ram); | |
setUserMode(pPort->ProObj, FALSE); | |
USLPUT3("read: ram:%d value:0x%x.\n", ram, read_value); | |
return 0; | |
} | |
static s8 si_ram_get( Port_t *pPort, u8 *parm, const u8 size) | |
{ | |
u32 temp = 0; | |
u16 addr = 0; | |
if(NULL == pPort) | |
{ | |
USLPUT0("si_ram_get pPort NULL \n"); | |
return -1; | |
} | |
addr = *(u16 *)parm; | |
printk("SLIC read ram %d\n", addr); | |
setUserMode(pPort->ProObj, TRUE); | |
temp = ctrl_ReadRAMWrapper(pPort->ProObj->deviceId->ctrlInterface->hCtrl, pPort->ProObj->channel, addr); | |
*((u32 *)parm) = temp; | |
setUserMode(pPort->ProObj, FALSE); | |
USLPUT3("addr %d, data 0x%x\n", addr, temp); | |
return 0; | |
} | |
static s8 si_update_ringpara(SILAB_CFG_CHIP_t *ptOldCfg, u8 ringvol_param) | |
{ | |
u32 dwNewRing = RING_F20_45VRMS_0VDC_LPR; | |
switch (ringvol_param) | |
{ | |
#if 0 | |
case RING_VOLTAGE_55VPK: | |
dwNewRing = RING_F25_40VRMS_0VDC_BAL; /* 40vrms */ | |
break; | |
case RING_VOLTAGE_65VPK: | |
dwNewRing = RING_F25_45VRMS_0VDC_BAL; /* 45vrms */ | |
break; | |
case RING_VOLTAGE_70VPK: | |
dwNewRing = RING_F25_50VRMS_0VDC_BAL; /* 50vrms */ | |
break; | |
case RING_VOLTAGE_75VPK: | |
dwNewRing = RING_F25_55VRMS_0VDC_BAL; /* 55vrms */ | |
break; | |
case RING_VOLTAGE_85VPK: | |
dwNewRing = RING_F25_60VRMS_0VDC_BAL; /* 60vrms */ | |
break; | |
#endif | |
default: | |
dwNewRing = RING_F20_45VRMS_0VDC_LPR; /* 50vrms */ | |
break; | |
} | |
if (dwNewRing != ptOldCfg->ring) | |
{ | |
ptOldCfg->ring = dwNewRing; | |
return 1; | |
} | |
return 0; | |
} | |
static s8 si_ring_cfg(Port_t *pPort, u8 ringvol_param) | |
{ | |
if(NULL == pPort) | |
{ | |
USLPUT0("si3217x cfg ringvpk with NULL pointer pPort!\n"); | |
return -1; | |
} | |
if (1 == si_update_ringpara(pPort->pPreCfg, ringvol_param)) | |
{ | |
ProSLIC_RingSetup(pPort->ProObj, pPort->pPreCfg->ring); | |
} | |
return 0; | |
} | |
static s8 si_update_dcpara(SILAB_CFG_CHIP_t *ptOldCfg, u8 vol_param, u8 cur_param) | |
{ | |
u32 dwNewDc = DCFEED_48V_20MA; | |
switch (vol_param) | |
{ | |
case DC_VOLTAGE_48V: | |
switch (cur_param) | |
{ | |
#if 0 | |
case DC_CURRENT_20MA: | |
dwNewDc = DCFEED_48V_20MA; /* 48v20mA */ | |
break; | |
case DC_CURRENT_24MA: | |
dwNewDc = DCFEED_48V_24MA; /* 48v24mA */ | |
break; | |
case DC_CURRENT_28MA: | |
dwNewDc = DCFEED_48V_28MA; /* 48v28mA */ | |
break; | |
case DC_CURRENT_32MA: | |
dwNewDc = DCFEED_48V_32MA; /* 48v32mA */ | |
break; | |
#endif | |
default: | |
dwNewDc = DCFEED_48V_25MA; /* 48v25mA */ | |
break; | |
} | |
break; | |
case DC_VOLTAGE_52V: | |
switch (cur_param) | |
{ | |
#if 0 | |
case DC_CURRENT_20MA: | |
dwNewDc = DCFEED_52V_20MA; /* 52v20mA */ | |
break; | |
case DC_CURRENT_24MA: | |
dwNewDc = DCFEED_52V_24MA; /* 52v24mA */ | |
break; | |
case DC_CURRENT_28MA: | |
dwNewDc = DCFEED_52V_28MA; /* 52v28mA */ | |
break; | |
case DC_CURRENT_32MA: | |
dwNewDc = DCFEED_52V_32MA; /* 52v32mA */ | |
break; | |
#endif | |
default: | |
dwNewDc = DCFEED_48V_25MA; /* 48v25mA */ | |
break; | |
} | |
break; | |
default: | |
dwNewDc = DCFEED_48V_25MA; /* 48v25mA */ | |
break; | |
} | |
if (dwNewDc != ptOldCfg->dc) | |
{ | |
ptOldCfg->dc = dwNewDc; | |
return 1; | |
} | |
return 0; | |
} | |
static s8 si_dcfeed_cfg(Port_t *pPort, u8 vol_param, u8 cur_param) | |
{ | |
if(pPort == NULL) | |
{ | |
USLPUT0("si3217x cfg dcfeed with NULL pointer pPort!\n"); | |
return -1; | |
} | |
if (1 == si_update_dcpara(pPort->pPreCfg, vol_param, cur_param)) | |
{ | |
ProSLIC_DCFeedSetup(pPort->ProObj, pPort->pPreCfg->dc); | |
} | |
return 0; | |
} | |
static s8 si_disable_powersave(Port_t *pPort) | |
{ | |
u8 bData = 0; | |
bData = ctrl_ReadRegisterWrapper(pPort->ProObj->deviceId->ctrlInterface->hCtrl, pPort->ProObj->channel, SI3217X_COM_REG_ENHANCE); | |
bData &= ~0x10; | |
ctrl_WriteRegisterWrapper(pPort->ProObj->deviceId->ctrlInterface->hCtrl, pPort->ProObj->channel,SI3217X_COM_REG_ENHANCE, bData); | |
return 0; | |
} | |
static s8 si_electric_set(Port_t *pPort, const u16 port, const ELECTRIC_CFG_CUSTOMIZED *buf) | |
{ | |
s8 ret = 0; | |
u8 bRingVol = 0; | |
u8 bDcVol = 0; | |
u8 bDcCur = 0; | |
if((NULL == pPort) || (buf == NULL)) | |
{ | |
USLPUT0("si_electric_set pPort/buf NULL \n"); | |
return -1; | |
} | |
bRingVol = buf->bCusRingVpk; | |
bDcVol = buf->bCusDcVol; | |
bDcCur = buf->bCusDcLoopCurr; | |
#if 0 | |
switch(buf->bScene) | |
{ | |
case DB_SLC_SINGLEPHONE_SHORTLOOP: | |
bRingVol = RING_VOLTAGE_70VPK; | |
bDcVol = DC_VOLTAGE_48V; | |
bDcCur = DC_CURRENT_20MA; | |
break; | |
case DB_SLC_MULTIPHONES_SHORTLOOP: | |
bRingVol = RING_VOLTAGE_70VPK; | |
bDcVol = DC_VOLTAGE_48V; | |
bDcCur = DC_CURRENT_32MA; | |
break; | |
case DB_SLC_LONGLOOP: | |
bRingVol = RING_VOLTAGE_85VPK; | |
bDcVol = DC_VOLTAGE_52V; | |
bDcCur = DC_CURRENT_20MA; | |
break; | |
case DB_SLC_ORIGINAL_FACTORY: | |
bRingVol = RING_VOLTAGE_70VPK; | |
bDcVol = DC_VOLTAGE_48V; | |
bDcCur = DC_CURRENT_20MA; | |
break; | |
case DB_SLC_CUSTOMIZED: | |
/* use customized parameters */ | |
break; | |
default: | |
USLPUT0("\n Not support scence:%d \n", buf->bScene); | |
break; | |
} | |
#endif | |
USLPUT3("si_electric_set Ring_vol: %d Dc_vol: %d Dc_cur: %d\n", bRingVol, bDcVol, bDcCur); | |
ret = si_dcfeed_cfg(pPort, bDcVol, bDcCur); | |
if(ret) | |
{ | |
USLPUT0("si_dcfeed_cfg fail !!! \n"); | |
} | |
ret = si_ring_cfg(pPort, bRingVol); | |
if(ret) | |
{ | |
USLPUT0("si_ring_cfg fail !!! \n"); | |
} | |
return 0; | |
} | |
static s8 si_time_cfg(Port_t *pPort, const USL_CONFIG *Slc_Time_Cfg) | |
{ | |
if((NULL == pPort) || (NULL == Slc_Time_Cfg)) | |
{ | |
USLPUT0("si_time_cfg pPort/Slc_Time_Cfg NULL \n"); | |
return -1; | |
} | |
pPort->stUslConf.hookonmin = MS2JIFF(Slc_Time_Cfg->hookonmin, 10) + 2; | |
pPort->stUslConf.hookoffmin = MS2JIFF(Slc_Time_Cfg->hookoffmin, 10) - 2; | |
pPort->stUslConf.prehookoff = MS2JIFF(Slc_Time_Cfg->prehookoff, 10) - 2; | |
pPort->stUslConf.flash_low_min = MS2JIFF(Slc_Time_Cfg->flash_low_min, 10) - 2; | |
pPort->stUslConf.flash_low_max = MS2JIFF(Slc_Time_Cfg->hookonmin, 10) + 2; | |
pPort->stUslConf.flash_high_fix = MS2JIFF(Slc_Time_Cfg->flash_high_fix, 10) - 2; | |
pPort->stUslConf.dial_high_min = MS2JIFF(Slc_Time_Cfg->dial_high_min, 10) - 2; | |
pPort->stUslConf.dial_high_max = MS2JIFF(Slc_Time_Cfg->dial_high_max, 10) + 2; | |
pPort->stUslConf.dial_low_min = MS2JIFF(Slc_Time_Cfg->dial_low_min, 10) - 2; | |
pPort->stUslConf.dial_low_max = MS2JIFF(Slc_Time_Cfg->dial_low_max, 10) + 2; | |
return 0; | |
} | |
static s8 si_slctool_time_cfg(Port_t *pPort, SLIC_IOCTL_CMD cmd, u16 wTime) | |
{ | |
if(NULL == pPort) | |
{ | |
USLPUT0("si_slctool_time_cfg pPort NULL \n"); | |
return -1; | |
} | |
switch(cmd) | |
{ | |
case SLIC_CFG_HOOK_LOWLEN: | |
case SLIC_CFG_FLASH_LMAX: | |
pPort->stUslConf.hookonmin = MS2JIFF(wTime, 10) + 2; | |
pPort->stUslConf.flash_low_max = MS2JIFF(wTime, 10) + 2; | |
break; | |
case SLIC_CFG_HOOK_HIGLEN: | |
pPort->stUslConf.hookoffmin = MS2JIFF(wTime, 10) - 2; | |
break; | |
case SLIC_CFG_PREHOOK_HIGLEN: | |
pPort->stUslConf.prehookoff = MS2JIFF(wTime, 10) - 2; | |
break; | |
case SLIC_CFG_FLASH_LMIN: | |
pPort->stUslConf.flash_low_min = MS2JIFF(wTime, 10) - 2; | |
break; | |
case SLIC_CFG_FLASH_HFIX: | |
pPort->stUslConf.flash_high_fix = MS2JIFF(wTime, 10) - 2; | |
break; | |
case SLIC_CFG_DIAL_HMIN: | |
pPort->stUslConf.dial_high_min = MS2JIFF(wTime, 10) - 2; | |
break; | |
case SLIC_CFG_DIAL_HMAX: | |
pPort->stUslConf.dial_high_max = MS2JIFF(wTime, 10) + 2; | |
break; | |
case SLIC_CFG_DIAL_LMIN: | |
pPort->stUslConf.dial_low_min = MS2JIFF(wTime, 10) - 2; | |
break; | |
case SLIC_CFG_DIAL_LMAX: | |
pPort->stUslConf.dial_low_max = MS2JIFF(wTime, 10) + 2; | |
break; | |
default: | |
USLPUT0("cmd=%d not found!\n", cmd); | |
break; | |
} | |
return 0; | |
} | |
static void InitPortsData(int port) | |
{ | |
if (port >= MAX_PORT_NUM) | |
{ | |
USLPUT0("InitPortsData port %d fail\n", port); | |
return; | |
} | |
ports[port].hook_state = HOOKON; | |
ports[port].pulse_dig = 0; | |
ports[port].stLineTestPara.si_item = 0xff; | |
ports[port].stLineTestPara.test_flg = NOT_TEST; | |
ports[port].stLineTestPara.cnt = 0; | |
ports[port].low_len = 0; | |
ports[port].high_len = 0; | |
ports[port].stUslConf.hookonmin = MS2JIFF(100, 10)/10; | |
ports[port].stUslConf.hookoffmin = MS2JIFF(10, 10)/10; | |
ports[port].stUslConf.prehookoff = MS2JIFF(6, 10)/10; | |
ports[port].stUslConf.flash_low_min = MS2JIFF(4, 10)/10; | |
ports[port].stUslConf.flash_low_max = MS2JIFF(40, 10)/10; | |
ports[port].stUslConf.flash_high_fix = MS2JIFF(25, 10)/10; | |
ports[port].stUslConf.dial_high_min = MS2JIFF(3, 10)/10; | |
ports[port].stUslConf.dial_high_max = MS2JIFF(12, 10)/10; | |
ports[port].stUslConf.dial_low_min = MS2JIFF(4, 10)/10; | |
ports[port].stUslConf.dial_low_max = MS2JIFF(15, 10)/10; | |
/* add slic inf pre cfg to port struct */ | |
ports[port].pPreCfg = &BoardCfg[port]; | |
return; | |
} | |
int InitSiliconBoard(void) | |
{ | |
int i = 0; | |
int dwInitCh = 0; | |
int devtpye = -1; | |
int ret = 0; | |
USL_PORT_MAP *p = NULL; | |
SlicHardReset(); | |
for(i = 0; i < MAX_PORT_NUM; i++) | |
{ | |
p = get_port_item(i, SLIC_PORT_TYPE ); | |
if(NULL != p) | |
{ | |
#ifdef DEBUG_SLIC_ON | |
USLPUT0("Init port %d\n", i); | |
#endif | |
spiGciObj[i].port = p->cs; | |
ProSLIC_createControlInterface(&ProHWIntf[i]); | |
ProSLIC_createDevice(&(ProSLICDevices[i])); | |
ProSLIC_createChannel(&ports[i].ProObj); | |
devtpye = VerifyChipID(&spiGciObj[i], p->chan); | |
if(-1 != devtpye) | |
{ | |
ProSLIC_SWInitChan(ports[i].ProObj,p->chan,devtpye,ProSLICDevices[i],ProHWIntf[i]); | |
ProSLIC_setSWDebugMode(ports[i].ProObj,true); /* optional */ | |
ProSLIC_setControlInterfaceCtrlObj (ProHWIntf[i], &spiGciObj[i]); | |
ProSLIC_setControlInterfaceReset (ProHWIntf[i], ctrl_ResetWrapper); | |
ProSLIC_setControlInterfaceWriteRegister (ProHWIntf[i], ctrl_WriteRegisterWrapper); | |
ProSLIC_setControlInterfaceReadRegister (ProHWIntf[i], ctrl_ReadRegisterWrapper); | |
ProSLIC_setControlInterfaceWriteRAM (ProHWIntf[i], ctrl_WriteRAMWrapper); | |
ProSLIC_setControlInterfaceReadRAM (ProHWIntf[i], ctrl_ReadRAMWrapper); | |
ProSLIC_setControlInterfaceTimerObj (ProHWIntf[i], &timerObj); | |
ProSLIC_setControlInterfaceDelay (ProHWIntf[i], time_DelayWrapper); | |
ProSLIC_setControlInterfaceTimeElapsed (ProHWIntf[i], time_TimeElapsedWrapper); | |
ProSLIC_setControlInterfaceGetTime (ProHWIntf[i], time_GetTimeWrapper); | |
ProSLIC_setControlInterfaceSemaphore (ProHWIntf[i], SiSetSemaphore); | |
ProSLIC_Reset(ports[i].ProObj); | |
arrayOfProslicChans[i] = ports[i].ProObj; | |
#ifdef SI3218X | |
(arrayOfProslicChans[i])->deviceId->chipType=SI32185; | |
#endif | |
dwInitCh++; | |
} | |
else | |
{ | |
#ifdef DEBUG_SLIC_ON | |
USLPUT0("No Siliconlab chip was found!!\n"); | |
#endif | |
} | |
} | |
} | |
if (0 == dwInitCh) | |
{ | |
USLPUT0("No Siliconlab chip need to be initialized!!\n"); | |
return -1; | |
} | |
#ifdef SIVOICE_MULTI_BOM_SUPPORT | |
printk("ProSLIC_Init_MultiBOM\n"); | |
ret = ProSLIC_Init_MultiBOM(arrayOfProslicChans,dwInitCh,BoardCfg[0].generel_cfg); | |
#else | |
printk("ProSLIC_Init\n"); | |
ret = ProSLIC_Init(arrayOfProslicChans,dwInitCh); | |
#endif | |
if(0 != ret) | |
{ | |
printk("howard ProSLIC_Init_MultiBOM return %d\n", ret); | |
return ret; | |
} | |
/* as to 32260 can make some phone crash, and no need to do this for short subscriber line, so don't use it again */ | |
//ProSLIC_LBCal(arrayOfProslicChans,dwInitCh); | |
for(i = 0; i < dwInitCh; i++) | |
{ | |
USLPUT3("get_port_item port:%d.\n",i); | |
p = get_port_item(i, SLIC_PORT_TYPE ); | |
if (NULL != p) | |
{ | |
USLPUT3("channelEnable:%d.\n",ports[i].ProObj->channelEnable); | |
if( 1 == ports[i].ProObj->channelEnable ) | |
{ | |
USLPUT3("Register the port:%d.\n",i); | |
InitPortsData(i); | |
InitSiliconChip(&ports[i]); | |
usrline_port_register(p->port, p->type, &si_ops, &ports[i]); | |
} | |
else | |
{ | |
USLPUT0("port:%d disabled.\n",i); | |
return -1; | |
} | |
} | |
} | |
//init_flg = 1; | |
return 0; | |
} | |
int SiSetSemaphore(void *pHCtrl, int s) | |
{ | |
/* Only slic use spi */ | |
return 1; | |
} | |
/* handle the event */ | |
int HandleSiEvent(Port_t *pPort, proslicIntType *pIntData) | |
{ | |
int i = 0; | |
ProslicInt IntData ; | |
i = pIntData->number; | |
while(i--) | |
{ | |
IntData = pIntData->irqs[i]; | |
#ifdef DEBUG_SLIC_ON | |
switch(IntData) | |
{ | |
case IRQ_VBAT: | |
/* The sensed battery voltage differs from the nominal VBAT value by an amount exceeding a programmed threshold. */ | |
USLPUT2(" Error:VBAT_IA.\n"); | |
break; | |
case IRQ_RING_TRIP: | |
break; | |
case IRQ_LOOP_STATUS: | |
/* Hookoff */ | |
break; | |
case IRQ_LONG_STAT: | |
/* LONG_HI_IA */ | |
USLPUT2(" Error: LONG_HI_IA.\n"); | |
break; | |
case IRQ_VOC_TRACK: | |
/* The sensed battery voltage cannot support the programmed differential voltage. */ | |
USLPUT2(" Error: VOC_TRACK_IA.\n"); | |
break; | |
case IRQ_MADC_FS: | |
break; | |
case IRQ_P_HVIC: | |
/* a hardware power alarm based on the total chip power dissipation by the HVIC. */ | |
USLPUT2(" Error:IRQ_P_HVIC.\n"); | |
break; | |
case IRQ_P_THERM: | |
/* A hardware power alarm. */ | |
USLPUT2(" Error:P_THERM_IA.\n"); | |
break; | |
case IRQ_OSC1_T1: | |
case IRQ_OSC1_T2: | |
case IRQ_OSC2_T1: | |
case IRQ_OSC2_T2: | |
case IRQ_RING_T1: | |
case IRQ_RING_T2: | |
case IRQ_PM_T1: | |
case IRQ_PM_T2: | |
case IRQ_FSKBUF_AVAIL: | |
case IRQ_P_OFFLD: | |
case IRQ_DTMF: | |
case IRQ_INDIRECT: | |
case IRQ_TXMDM: | |
case IRQ_RXMDM: | |
case IRQ_PQ1: | |
case IRQ_PQ2: | |
case IRQ_PQ3: | |
case IRQ_PQ4: | |
case IRQ_PQ5: | |
case IRQ_PQ6: | |
case IRQ_RING_FAIL: | |
case IRQ_CM_BAL: | |
case IRQ_USER_0: | |
case IRQ_USER_1: | |
case IRQ_USER_2: | |
case IRQ_USER_3: | |
case IRQ_USER_4: | |
case IRQ_USER_5: | |
case IRQ_USER_6: | |
case IRQ_USER_7: | |
case IRQ_DSP: | |
break; | |
default: | |
break; | |
} | |
#endif | |
} | |
return 0; | |
} | |
void SiScanSignals(USL_PORT *usl_port, u8 hook) | |
{ | |
Port_t *data = usl_port->pLine; | |
SiUpdatePort(data, usl_port->port, hook); | |
switch(data->hook_state) | |
{ | |
case HOOKON: | |
break; | |
case HOOKOFFING: | |
if ( data->high_len == data->stUslConf.prehookoff ) | |
{ | |
/* User Pre HookOff! report */ | |
} | |
if ( data->high_len < data->stUslConf.hookoffmin ) | |
{ | |
return; | |
} | |
//usrline_report(usl_port->port, EV_FXS_PRE_HOOKOFF, 0, usl_port->event_mask); | |
/* Finished. change state to HOOKOFF */ | |
data->hook_state = HOOKOFF; | |
/* User HookOff! report */ | |
//ProSLIC_SetLinefeedStatus( data->ProObj, LF_FWD_ACTIVE );?? | |
usrline_report(usl_port->port,EV_FXS_HOOKOFF,0, usl_port->event_mask); | |
slic_offhook = 1; | |
break; | |
case HOOKOFF: | |
if (data->high_len == data->stUslConf.flash_high_fix && | |
data->low_len < data->stUslConf.hookonmin && data->low_len >= data->stUslConf.dial_low_min ) | |
{ | |
if (data->pulse_dig == FLASH_EV_FLG) | |
{ | |
USLPUT2("EV_FXS_FLASH: line=%d,low=%d. high %d\n",usl_port->port, data->low_len,data->high_len); | |
usrline_report(usl_port->port,EV_FXS_FLASH,0, usl_port->event_mask); | |
} | |
else if (( 1 <= data->pulse_dig ) && ( 10 >= data->pulse_dig )) | |
{ | |
USLPUT2("EV_FXS_COLLECT_DIG: line=%d,low=%d. high %d\n",usl_port->port, data->low_len,data->high_len); | |
usrline_report(usl_port->port,EV_FXS_COLLECT_DIG,data->pulse_dig%10, usl_port->event_mask); | |
} | |
else | |
{ | |
USLPUT2("drop dig:%d! line=%d, low %d, high %d\n", usl_port->port, data->pulse_dig, data->low_len, data->high_len); | |
} | |
data->pulse_dig = 0; | |
} | |
break; | |
case HOOKONING: | |
if (data->low_len < data->stUslConf.hookonmin) | |
{ | |
//printk("low_len %d < hookonmin %d, return\n", data->low_len, data->stUslConf.hookonmin); | |
return; | |
} | |
/* Finished. change state to HOOKON */ | |
//printk("low_len %d < hookonmin %d\n", data->low_len, data->stUslConf.hookonmin); | |
data->hook_state = HOOKON; | |
/* User HookOn! report */ | |
data->pulse_dig = 0; | |
data->bDialEn = EV_DIAL_STOP; | |
usrline_report(usl_port->port,EV_FXS_HOOKON,0,usl_port->event_mask); | |
slic_offhook = 0; | |
break; | |
default: | |
break; | |
} | |
} | |
void SiUpdatePort(Port_t *data, u16 port, u8 event) | |
{ | |
if (event == EV_LOW) | |
{ | |
data->low_len++; | |
switch (data->hook_state) | |
{ | |
case HOOKOFFING: | |
/* short pulse filter */ | |
if (data->low_len > PULSE_FILTER_TIME) | |
{ | |
data->hook_state = HOOKON; | |
data->low_len = 0; | |
} | |
else | |
{ | |
data->high_len++; | |
} | |
break; | |
case HOOKOFF: | |
if (data->low_len > PULSE_FILTER_TIME) | |
{ | |
data->hook_state = HOOKONING; | |
data->low_len = 0; | |
} | |
else | |
{ | |
data->high_len++; | |
} | |
break; | |
default: | |
break; | |
} | |
} | |
else | |
{ | |
data->high_len++; | |
switch (data->hook_state) | |
{ | |
case HOOKON: | |
if (data->high_len > PULSE_FILTER_TIME) | |
{ | |
data->hook_state = HOOKOFFING; | |
data->high_len = 0; | |
} | |
else | |
{ | |
data->low_len++; | |
} | |
break; | |
case HOOKONING: | |
if (data->high_len > PULSE_FILTER_TIME) | |
{ | |
data->hook_state = HOOKOFF; | |
/* To Judge if there is a pulse occured */ | |
if((EV_DIAL_START == data->bDialEn) && (data->low_len >= data->stUslConf.dial_low_min) && | |
(data->low_len < data->stUslConf.dial_low_max)) | |
{ | |
data->pulse_dig++; | |
USLPUT3("port:%d pulse_dig++! low %d, high %d, dig %d\n", port, data->low_len, data->high_len, data->pulse_dig); | |
} | |
else if(data->low_len >= data->stUslConf.flash_low_min) | |
{ | |
data->pulse_dig = FLASH_EV_FLG; | |
USLPUT3("port:%d Flash! low %d, high %d\n", port, data->low_len, data->high_len); | |
} | |
else | |
{ | |
USLPUT3("port:%d Pulse not dientfied! low %d, high %d\n", port, data->low_len, data->high_len); | |
} | |
data->high_len = 0; | |
} | |
else | |
{ | |
data->low_len++; | |
} | |
break; | |
default: | |
break; | |
} | |
} | |
} | |
void InitSiliconChip(Port_t *pPort) | |
{ | |
/* DC */ | |
ProSLIC_DCFeedSetup(pPort->ProObj, pPort->pPreCfg->dc); | |
//ProSLIC_SetLinefeedStatus(pPort->ProObj, pPort->pPreCfg->linestaus); | |
/* Ring init */ | |
ProSLIC_RingSetup(pPort->ProObj, pPort->pPreCfg->ring); | |
/* PCM init */ | |
ProSLIC_PCMSetup(pPort->ProObj, pPort->pPreCfg->a_u_law); | |
ProSLIC_PCMTimeSlotSetup(pPort->ProObj,0x1,0x1); | |
ProSLIC_ZsynthSetup(pPort->ProObj, pPort->pPreCfg->Impe); | |
ProSLIC_ToneGenSetup(pPort->ProObj, pPort->pPreCfg->tone); | |
/* Meter init */ | |
//ProSLIC_PulseMeterSetup(pPort->ProObj, pPort->pPreCfg->meter); | |
ProSLIC_FSKSetup(pPort->ProObj, ITU_FSK); | |
ProSLIC_AudioGainSetup(pPort->ProObj, pPort->pPreCfg->rxgain, pPort->pPreCfg->txgain, pPort->pPreCfg->Impe); | |
/* Active the line */ | |
ProSLIC_EnableInterrupts(pPort->ProObj); | |
ProSLIC_SetLinefeedStatus(pPort->ProObj,LF_FWD_ACTIVE); | |
if (1 == pPort->pPreCfg->bDisablePowerSave) | |
{ | |
si_disable_powersave(pPort); | |
} | |
return; | |
} | |
int SiRemoveBoard(void) | |
{ | |
int i = 0; | |
USL_PORT_MAP *p = NULL; | |
for( i = 0; i <MAX_PORT_NUM; i++ ) | |
{ | |
p = get_port_item(i, SLIC_PORT_TYPE); | |
if(p != NULL) | |
{ | |
if (1 == ports[i].ProObj->channelEnable) | |
{ | |
USLPUT3("shutdown port:%d, ch:%d\n", i, ports[i].ProObj->channel); | |
/* reset chip */ | |
ProSLIC_Reset(ports[i].ProObj); | |
} | |
p->cs = 0; | |
p->chan = 0; | |
p->port = 0; | |
/* free chip related memory */ | |
ProSLIC_destroyChannel(&ports[i].ProObj); | |
ProSLIC_destroyDevice(&(ProSLICDevices[i])); | |
ProSLIC_destroyControlInterface(&ProHWIntf[i]); | |
} | |
} | |
return 0; | |
} | |
int ProSLIC_DTMFValid (proslicChanType_ptr pProslic) | |
{ | |
int valid_tone = 0; | |
if(pProslic->channelType != PROSLIC) | |
{ | |
return RC_IGNORE; | |
} | |
valid_tone = ctrl_ReadRegisterWrapper( pProslic->deviceId->ctrlInterface->hCtrl, | |
pProslic->channel,PROSLIC_REG_TONDTMF ) & 0x10; | |
if(valid_tone) | |
return 1; | |
else | |
return 0; | |
} | |
void ScanSiBoard(USL_PORT *pUslPort) | |
{ | |
u8 hook = 0; | |
int ret = 0; | |
switch (pUslPort->pLine->stLineTestPara.test_flg) | |
{ | |
case NOT_TEST: | |
if(dtmf_mute) | |
{ | |
ret = ProSLIC_DTMFValid(pUslPort->pLine->ProObj); | |
if(!ret) | |
{ | |
//ProSLIC_SetMuteStatus(pUslPort->pLine->ProObj,PROSLIC_MUTE_NONE); | |
dtmf_mute = 0; | |
} | |
} | |
//ProSLIC_ReadHookStatus(pUslPort->pLine->ProObj,&hook); | |
hook = slic_offhook; | |
SiScanSignals(pUslPort, hook); | |
break; | |
case TEST_STARTING: | |
case TEST_STOPING: | |
USLPUT3("change state:%d,do nothing\n", pUslPort->pLine->stLineTestPara.test_flg); | |
break; | |
case TESTING: | |
SiMltScan(pUslPort->pLine); | |
break; | |
default: | |
USLPUT0("unknow test state:%d\n", pUslPort->pLine->stLineTestPara.test_flg); | |
break; | |
} | |
return; | |
} | |
int VerifyChipID(ctrl_S *hCtrl, u8 chan) | |
{ | |
u8 id = 0; | |
int devtype = 0; | |
id = ctrl_ReadRegisterWrapper(hCtrl, chan,SI3217X_COM_REG_ID); | |
printk("Siliconlab chip cs:%d ch:%d id! 0x%x \n",hCtrl->port, chan, id); | |
USLPUT0("Siliconlab chip cs:%d ch:%d id! 0x%x \n", hCtrl->port, chan, id); | |
#if 0 | |
if (0xFF == id) | |
{ | |
USLPUT0("Siliconlab chip cs:%d ch:%d id error! 0x%x \n", hCtrl->port, chan, id); | |
return devtype; | |
} | |
switch(id&0xc0) | |
{ | |
case 0x80: | |
devtype = SI3217X_TYPE; | |
USLPUT0("Siliconlab chip Si3217x found! id:0x%x\n", id); | |
break; | |
case 0xc0: | |
devtype = SI3226X_TYPE; | |
USLPUT0("Siliconlab chip Si3226x found! id:0x%x\n", id); | |
break; | |
default: | |
USLPUT0("Siliconlab chip id error! 0x%x \n",id); | |
break; | |
} | |
#endif | |
#if 0 | |
switch( (id & 0x38) >> 3 ) | |
{ | |
case 0:/* Si32171 */ | |
#ifdef DEBUG_SLIC_ON | |
printk("Siliconlab chip Si32171 found!\n"); | |
#endif | |
break; | |
case 3:/* Si32175 */ | |
#ifdef DEBUG_SLIC_ON | |
printk("Siliconlab chip Si32175 found!\n"); | |
#endif | |
break; | |
case 4:/* Si32176 */ | |
#ifdef DEBUG_SLIC_ON | |
printk("Siliconlab chip Si32176 found!\n"); | |
#endif | |
break; | |
case 5:/* Si32177 */ | |
#ifdef DEBUG_SLIC_ON | |
printk("Siliconlab chip Si32177 found!\n"); | |
#endif | |
break; | |
case 6:/* Si32178 */ | |
#ifdef DEBUG_SLIC_ON | |
printk("Siliconlab chip Si32178 found!\n"); | |
#endif | |
break; | |
default: | |
printk("Siliconlab chip id error! 0x%x \n",id); | |
return -1; | |
} | |
#endif | |
return SI3217X_TYPE; | |
} | |
int ProSLIC_PCMCfg (proslicChanType_ptr hProslic,u8 preset) | |
{ | |
ctrl_WriteRegisterWrapper(hProslic->deviceId->ctrlInterface->hCtrl,hProslic->channel,SI3217X_COM_REG_PCMMODE,pcmcfg[preset]); | |
return 0; | |
} | |
int ProSLIC_PCMEnable (proslicChanType_ptr hProslic, u8 enable ) | |
{ | |
u8 data = 0; | |
data = ctrl_ReadRegisterWrapper( hProslic->deviceId->ctrlInterface->hCtrl,hProslic->channel,SI3217X_COM_REG_PCMMODE ); | |
if( enable ) | |
{ | |
data |= 0x10; | |
} | |
else | |
{ | |
data &= 0xef; | |
} | |
ctrl_WriteRegisterWrapper(hProslic->deviceId->ctrlInterface->hCtrl,hProslic->channel,SI3217X_COM_REG_PCMMODE, data); | |
return 0; | |
} | |
int ProSLIC_GetLinefeedStatus (proslicChanType_ptr hProslic, uInt8 *pLinefeed) | |
{ | |
u8 data = 0; | |
data = ctrl_ReadRegisterWrapper(hProslic->deviceId->ctrlInterface->hCtrl,hProslic->channel,SI3217X_COM_REG_LINEFEED); | |
*pLinefeed = data&0xf; | |
return 1; | |
} | |
static int setUserMode (proslicChanType_ptr hProslic, BOOLEAN on) | |
{ | |
u8 data; | |
data = ctrl_ReadRegisterWrapper(hProslic->deviceId->ctrlInterface->hCtrl,hProslic->channel,SI3217X_COM_REG_TEST_CNTL); | |
if (((data&1) != 0) == on) | |
return 0; | |
ctrl_WriteRegisterWrapper(hProslic->deviceId->ctrlInterface->hCtrl,hProslic->channel,SI3217X_COM_REG_TEST_CNTL, 2); | |
ctrl_WriteRegisterWrapper(hProslic->deviceId->ctrlInterface->hCtrl,hProslic->channel,SI3217X_COM_REG_TEST_CNTL, 8); | |
ctrl_WriteRegisterWrapper(hProslic->deviceId->ctrlInterface->hCtrl,hProslic->channel,SI3217X_COM_REG_TEST_CNTL, 0xe); | |
ctrl_WriteRegisterWrapper(hProslic->deviceId->ctrlInterface->hCtrl,hProslic->channel,SI3217X_COM_REG_TEST_CNTL, 0); | |
return 0; | |
} | |
static void StartSiLineTest(Port_t *pPort, uInt8 TestId) | |
{ | |
if(NULL == pPort) | |
{ | |
USLPUT0("StartSiLineTest error input NULL pointer.\n"); | |
return; | |
} | |
USLPUT2("StartSiLineTest: line %d item %d!\n", pPort->stLineTestPara.pstResult->port, TestId); | |
pPort->stLineTestPara.pstMlt->Mlt.pProslic = pPort->ProObj; | |
MLTClearSettings(&pPort->stLineTestPara.pstMlt->Mlt); | |
MLTClearResults(&pPort->stLineTestPara.pstMlt->Mlt); | |
switch(TestId) | |
{ | |
case TI_LineVolt: | |
/* Call test state initalization function */ | |
ProSLIC_SetLinefeedStatus(pPort->ProObj, LF_OPEN); | |
pPort->stLineTestPara.si_item = TI_LineVolt; | |
ProSLIC_mlt_init_foreign_voltages(&pPort->stLineTestPara.pstMlt->vState,30); | |
pPort->stLineTestPara.test_flg = TESTING; | |
break; | |
/*case ROH_TEST: | |
id = LT_TID_ROH; Receiver Off-Hook indication | |
break; */ | |
case TI_LineCap: | |
ProSLIC_SetLinefeedStatus(pPort->ProObj, LF_OPEN); | |
pPort->stLineTestPara.si_item = TI_LineCap; | |
ProSLIC_mlt_init_capacitance(&pPort->stLineTestPara.pstMlt->CapState); | |
pPort->stLineTestPara.test_flg = TESTING; | |
break; | |
case TI_LineRes: | |
ProSLIC_SetLinefeedStatus(pPort->ProObj, LF_OPEN); | |
pPort->stLineTestPara.si_item = TI_LineRes; /* Resistive Fault */ | |
/* Call test state initalization function */ | |
ProSLIC_mlt_init_resistive_faults(&pPort->stLineTestPara.pstMlt->rMeas); | |
pPort->stLineTestPara.test_flg = TESTING; | |
break; | |
case TI_LineRes_reverse: | |
ProSLIC_SetLinefeedStatus(pPort->ProObj, LF_OPEN); | |
pPort->stLineTestPara.si_item = TI_LineRes_reverse; /* Resistive Fault */ | |
/* Call test state initalization function */ | |
ProSLIC_mlt_init_resistive_faults(&pPort->stLineTestPara.pstMlt->rMeas); | |
pPort->stLineTestPara.test_flg = TESTING; | |
break;/**/ | |
/*case GR_909: | |
id = LT_TID_ALL_GR_909; All GR-909 fault tests in predefined order | |
break;*/ | |
/*case LOOP_BACK: | |
id = LT_TID_LOOPBACK; Loopback test | |
break;*/ | |
case TI_LoopCircuitAndRes: | |
pPort->stLineTestPara.si_item = TI_LoopCircuitAndRes; | |
/* DC Feed Self Test */ | |
pPort->stLineTestPara.test_flg = TEST_STOPING; | |
SiSendResultDCFeedSt(pPort); | |
break; | |
case TI_InLoopCurrent: | |
pPort->stLineTestPara.si_item = TI_InLoopCurrent; | |
/* DC Feed Self Test */ | |
pPort->stLineTestPara.test_flg = TEST_STOPING; | |
SiSendResultDCFeedSt(pPort); | |
break; | |
case TI_BatteryVolt: | |
/* DC VOLTAGE Test */ | |
pPort->stLineTestPara.si_item = TI_BatteryVolt; | |
pPort->stLineTestPara.test_flg = TEST_STOPING; | |
SiSendResultBatteryVol(pPort); | |
break; | |
case TI_RingVolt: | |
/* Ringing Self Test */ | |
ProSLIC_SetLinefeedStatus(pPort->ProObj, LF_RINGING); | |
pPort->stLineTestPara.si_item = TI_RingVolt; | |
pPort->stLineTestPara.test_flg = TESTING; | |
RingCnt = 0; | |
/**/ | |
break; | |
case ROH_TEST: | |
/* On/Off hook Self Test */ | |
pPort->stLineTestPara.si_item = TI_Hook; | |
pPort->stLineTestPara.test_flg = TEST_STOPING; | |
SiSendResultHook(pPort); | |
break; | |
case TI_REN: | |
ProSLIC_mlt_init_ren(&pPort->stLineTestPara.pstMlt->RenState); | |
ProSLIC_mlt_init_ren_cal(&pPort->stLineTestPara.pstMlt->Mlt); | |
pPort->stLineTestPara.si_item = TI_REN; | |
pPort->stLineTestPara.test_flg = TESTING; | |
break; | |
/*case QUICKTEST: | |
id = LT_TID_PRE_LINE_V; Pre Line Voltage Test | |
break;*/ | |
/*case 13: | |
id = LT_TID_FLT_DSCRM; Fault Discrimination Test | |
break;*/ | |
case TI_Outside12: | |
/*step 1: Line Voltage Test */ | |
/* Call test state initalization function */ | |
ProSLIC_SetLinefeedStatus(pPort->ProObj, LF_OPEN); | |
pPort->stLineTestPara.si_item = TI_LineVolt; | |
ProSLIC_mlt_init_foreign_voltages(&pPort->stLineTestPara.pstMlt->vState,30); | |
pPort->stLineTestPara.test_flg = TESTING; | |
break; | |
case TI_LineConnect: | |
/*Line Connectivity Test */ | |
StartLineConnectTest(pPort); | |
break; | |
default: | |
USLPUT1("The item is not surpported!\n"); | |
SendErrorTest(pPort, NOT_SURPPORT); | |
return; | |
} | |
return; | |
} | |
static s8 si_start_test(Port_t *pPort, const WriteCmd_t *Cmd) | |
{ | |
if((NULL == pPort) || (NULL == Cmd)) | |
{ | |
USLPUT0("si_start_test pPort/Cmd NULL pointer.\n"); | |
return -1; | |
} | |
if (TEST_STARTING == pPort->stLineTestPara.test_flg || TESTING == pPort->stLineTestPara.test_flg) | |
{ | |
USLPUT0("%s is under testing item:%d\n",__FUNCTION__, pPort->stLineTestPara.si_item); | |
return 0; | |
} | |
/* get test result memory */ | |
pPort->stLineTestPara.pstResult = (TestResult_t *)kmalloc(sizeof(TestResult_t), GFP_KERNEL); | |
if (NULL == pPort->stLineTestPara.pstResult) | |
{ | |
USLPUT0("%s port %d get TestResult memory failed!\n",__FUNCTION__, Cmd->port); | |
return -1; | |
} | |
memset(pPort->stLineTestPara.pstResult, 0, sizeof(TestResult_t)); | |
/* save test message */ | |
pPort->stLineTestPara.pstResult->port = Cmd->port; | |
pPort->stLineTestPara.pstResult->port_type = Cmd->port_type; | |
pPort->stLineTestPara.pstResult->item = Cmd->item; | |
pPort->stLineTestPara.pstResult->obligate = Cmd->obligate; | |
pPort->stLineTestPara.pstResult->num = Cmd->num; | |
pPort->stLineTestPara.pstResult->omci_item = Cmd->omci_item; | |
pPort->stLineTestPara.pstResult->flg = TEST_SUCC; | |
pPort->stLineTestPara.cnt = 0; | |
if((HOOKOFF == pPort->hook_state) && (0 == pPort->stLineTestPara.pstResult->obligate)) | |
{ | |
USLPUT1("The user is bust now!\n"); | |
SendErrorTest(pPort, TEST_USER_BUSY); | |
return -1; | |
} | |
/* get memory to save testing data */ | |
pPort->stLineTestPara.pstMlt = (ProSLICMLT *)kmalloc(sizeof(ProSLICMLT), GFP_KERNEL); | |
if (NULL == pPort->stLineTestPara.pstMlt) | |
{ | |
USLPUT0("%s port %d get Mlt memory failed!\n",__FUNCTION__, Cmd->port); | |
kfree(pPort->stLineTestPara.pstResult); | |
pPort->stLineTestPara.pstResult = NULL; | |
return -1; | |
} | |
memset(pPort->stLineTestPara.pstMlt, 0, sizeof(ProSLICMLT)); | |
pPort->stLineTestPara.test_flg = TEST_STARTING; | |
StartSiLineTest(pPort, pPort->stLineTestPara.pstResult->item); | |
return 0; | |
} | |
static s8 si_stop_test(Port_t *pPort) | |
{ | |
if(NULL == pPort) | |
{ | |
USLPUT0("si_stop_test pPort NULL \n"); | |
return -1; | |
} | |
if (TESTING == pPort->stLineTestPara.test_flg) | |
{ | |
pPort->stLineTestPara.test_flg = TEST_STOPING; | |
InitSiliconChip(pPort); | |
} | |
if (NULL != pPort->stLineTestPara.pstMlt) | |
{ | |
kfree(pPort->stLineTestPara.pstMlt); | |
} | |
pPort->stLineTestPara.pstMlt = NULL; | |
if (NULL != pPort->stLineTestPara.pstResult) | |
{ | |
kfree(pPort->stLineTestPara.pstResult); | |
} | |
pPort->stLineTestPara.pstResult = NULL; | |
pPort->stLineTestPara.test_flg = NOT_TEST; | |
return 0; | |
} | |
static s8 si_read_result(Port_t *pPort, TestResult_t *pstResult) | |
{ | |
if((NULL == pPort) || (NULL == pstResult)) | |
{ | |
USLPUT0("leg_read_result pPort/pstResult NULL pointer.\n"); | |
return -1; | |
} | |
if (NULL != pPort->stLineTestPara.pstMlt) | |
{ | |
kfree(pPort->stLineTestPara.pstMlt); | |
} | |
pPort->stLineTestPara.pstMlt = NULL; | |
if (NULL != pPort->stLineTestPara.pstResult) | |
{ | |
memcpy(pstResult, pPort->stLineTestPara.pstResult, sizeof(TestResult_t)); | |
kfree(pPort->stLineTestPara.pstResult); | |
} | |
pPort->stLineTestPara.pstResult = NULL; | |
pPort->stLineTestPara.test_flg = NOT_TEST; | |
USLPUT3("\npPort->stLineTestPara.cnt=%d\n", pPort->stLineTestPara.cnt); | |
return 0; | |
} | |
static s8 StartLineConnectTest(Port_t *pPort) | |
{ | |
if(NULL == pPort) | |
{ | |
USLPUT1("StartLineConnectTest pPort NULL.\n"); | |
return -1; | |
} | |
if(HOOKOFF == pPort->hook_state)//Õª»ú£¬Ôò±¨Óл°»ú | |
{ | |
pPort->stLineTestPara.pstResult->user_flg = 1; | |
usrline_report(pPort->stLineTestPara.pstResult->port,EV_FXS_TEST_DONE,0,0); | |
} | |
else //¹Ò»ú£¬Ôò²âREN | |
{ | |
pPort->stLineTestPara.pstResult->user_flg = 0; | |
ProSLIC_mlt_init_ren(&pPort->stLineTestPara.pstMlt->RenState); | |
ProSLIC_mlt_init_ren_cal(&pPort->stLineTestPara.pstMlt->Mlt); | |
pPort->stLineTestPara.si_item = TI_REN; | |
pPort->stLineTestPara.test_flg = TESTING; | |
} | |
return 0; | |
} | |
static s8 si_time_print(Port_t *pLine) | |
{ | |
USLPUT0("si32xxx times:\n"); | |
USLPUT0("hookonmin: %d\n",pLine->stUslConf.hookonmin); | |
USLPUT0("hookoffmin: %d\n",pLine->stUslConf.hookoffmin); | |
USLPUT0("prehookoff: %d\n",pLine->stUslConf.prehookoff); | |
USLPUT0("flash_low_min: %d\n",pLine->stUslConf.flash_low_min); | |
USLPUT0("flash_high_fix:%d\n",pLine->stUslConf.flash_high_fix); | |
USLPUT0("dial_high_min: %d\n",pLine->stUslConf.dial_high_min); | |
USLPUT0("dial_high_max: %d\n",pLine->stUslConf.dial_high_max); | |
USLPUT0("dial_low_min: %d\n",pLine->stUslConf.dial_low_min); | |
USLPUT0("dial_low_max: %d\n",pLine->stUslConf.dial_low_max); | |
USLPUT0("dial_enable: %d\n",pLine->bDialEn); | |
return 0; | |
} | |
static s8 si_dial_set(Port_t *pPort, u8 bDialEn) | |
{ | |
if(NULL == pPort) | |
{ | |
USLPUT1("si_dial_set pPort NULL.\n"); | |
return -1; | |
} | |
pPort->bDialEn = bDialEn; | |
return 0; | |
} | |
/* | |
** Clears REN cal flag | |
*/ | |
void MLTClearSettings(ProSLICMLTType *pProSLICMLT) | |
{ | |
pProSLICMLT->ren.renCalFlag = 0; | |
} | |
/* | |
** Clears any previous GR909 test results CDP move this to proslic_mlt.c | |
*/ | |
void MLTClearResults(ProSLICMLTType *pProSLICMLT) | |
{ | |
pProSLICMLT->hazVAC.measTG = 0; | |
pProSLICMLT->hazVAC.measTR = 0; | |
pProSLICMLT->hazVAC.measRG = 0; | |
pProSLICMLT->hazVAC.resultsValid = 0; | |
pProSLICMLT->hazVDC.measTG = 0; | |
pProSLICMLT->hazVDC.measTR = 0; | |
pProSLICMLT->hazVDC.measRG = 0; | |
pProSLICMLT->hazVDC.resultsValid = 0; | |
pProSLICMLT->resFaults.measTG = 10000000; | |
pProSLICMLT->resFaults.measTR = 10000000; | |
pProSLICMLT->resFaults.measRG = 10000000; | |
pProSLICMLT->resFaults.resultsValid = 0; | |
pProSLICMLT->roh.rohTrue = RC_MLT_ROH_NOFAULT; | |
pProSLICMLT->roh.resultsValid = 0; | |
pProSLICMLT->ren.renValue = 0; | |
pProSLICMLT->ren.resultsValid = 0; | |
} | |
void SiMltScan(Port_t *pPort) | |
{ | |
int done = 0; | |
pPort->stLineTestPara.cnt++; | |
if( pPort->stLineTestPara.cnt > MAX_TEST_TIMEOUT ) /* Test time out */ | |
{ | |
pPort->stLineTestPara.test_flg = TEST_STOPING; | |
InitSiliconChip(pPort); | |
ProSLIC_SetLinefeedStatus(pPort->ProObj, LF_FWD_ACTIVE); | |
SendErrorTest(pPort, TESTITEM_TIMEOVER); | |
return; | |
} | |
switch( pPort->stLineTestPara.si_item ) | |
{ | |
case TI_LineVolt: | |
/* Call test function - will return 1 when complete */ | |
done = ProSLIC_mlt_foreign_voltages(&pPort->stLineTestPara.pstMlt->Mlt,&pPort->stLineTestPara.pstMlt->vState); | |
if(1 == done) | |
{ | |
pPort->stLineTestPara.test_flg = TEST_STOPING; | |
/* */ | |
ProSLIC_SetLinefeedStatus(pPort->ProObj, LF_FWD_ACTIVE); | |
msleep(200); /* need more than 150ms to normal feed state */ | |
SiSendResultVol(pPort, &pPort->stLineTestPara.pstMlt->Mlt); | |
} | |
break; | |
case TI_LineCap: | |
done = ProSLIC_mlt_capacitance(&pPort->stLineTestPara.pstMlt->Mlt,&pPort->stLineTestPara.pstMlt->CapState); | |
if(1 == done) | |
{ | |
pPort->stLineTestPara.test_flg = TEST_STOPING; | |
#ifdef DEBUG_SLIC_ON | |
USLPUT2("InitSiChip port: %d.\n",pPort->stLineTestPara.pstResult->port); | |
#endif | |
InitSiliconChip(pPort); //added by fandi,because after the cap test, dsp can't receive 1 4 7 5 8. | |
if(HOOKOFF == pPort->hook_state)//Õª»ú״̬£¬ÖØÐÂÉèÖÃʱ϶ | |
{ | |
si_timeslot_set(pPort, pPort->stLineTestPara.pstResult->port, pPort->stLineTestPara.pstResult->port); | |
} | |
ProSLIC_SetLinefeedStatus(pPort->ProObj, LF_FWD_ACTIVE); | |
msleep(200); /* need more than 150ms to normal feed state */ | |
SiSendResultCap(pPort, &pPort->stLineTestPara.pstMlt->Mlt); /* Ringers test per FCC Part 68 REN def.*/ | |
} | |
break; | |
case TI_LineRes: | |
case TI_LineRes_reverse: | |
/* Call test function - will return 1 when complete */ | |
done = ProSLIC_mlt_resistive_faults(&pPort->stLineTestPara.pstMlt->Mlt,&pPort->stLineTestPara.pstMlt->rMeas); | |
if(1 == done) | |
{ | |
pPort->stLineTestPara.test_flg = TEST_STOPING; | |
ProSLIC_SetLinefeedStatus(pPort->ProObj, LF_FWD_ACTIVE); | |
msleep(200); /* need more than 150ms to normal feed state */ | |
SiSendResultRes(pPort, &pPort->stLineTestPara.pstMlt->Mlt); | |
} | |
break; | |
case TI_LoopCircuitAndRes: | |
case TI_InLoopCurrent: | |
break; | |
case TI_BatteryVolt: | |
break; | |
case TI_RingVolt: | |
USLPUT1("%s: %d .\n", __FUNCTION__, __LINE__); | |
RingVol[RingCnt%MAX_RING_CNT] = ctrl_ReadRAMWrapper(pPort->ProObj->deviceId->ctrlInterface->hCtrl,pPort->ProObj->channel,SI3217X_COM_RAM_MADC_VBAT); | |
RingCnt++; | |
if( RingCnt > (MAX_RING_CNT - 1)) | |
{ | |
RingCnt = 0; | |
pPort->stLineTestPara.test_flg = TEST_STOPING; | |
ProSLIC_SetLinefeedStatus(pPort->ProObj, LF_FWD_ACTIVE); | |
SiSendResultRingtouser(pPort); | |
} | |
break; | |
case TI_Hook: | |
break; | |
case TI_REN: | |
done = ProSLIC_mlt_ren(&pPort->stLineTestPara.pstMlt->Mlt, &pPort->stLineTestPara.pstMlt->RenState); | |
if( 1 == done ) | |
{ | |
pPort->stLineTestPara.test_flg = TEST_STOPING; | |
ProSLIC_SetLinefeedStatus(pPort->ProObj, LF_FWD_ACTIVE); | |
SiRen(pPort, &pPort->stLineTestPara.pstMlt->Mlt); | |
} | |
break; | |
/* case POWER_SUP_VOLT: | |
break;*/ | |
case TI_Outside12: | |
break; | |
case TI_LineConnect: | |
break; | |
default: | |
return ; | |
} | |
} | |
void SiSendResultVol(Port_t *pPort, ProSLICMLTType *pMlt) | |
{ | |
USLPUT2("V_TR:DC %d, AC %d\n",pMlt->hazVDC.measTR , (pMlt->hazVAC.measTR) / 10); | |
USLPUT2("V_TG:DC %d, AC %d\n",pMlt->hazVDC.measTG , (pMlt->hazVAC.measTG) / 10); | |
USLPUT2("V_RG:DC %d, AC %d\n",pMlt->hazVDC.measRG , (pMlt->hazVAC.measRG) / 10); | |
pPort->stLineTestPara.pstResult->vac_tr = pMlt->hazVAC.measTR; | |
pPort->stLineTestPara.pstResult->vac_tg = pMlt->hazVAC.measTG; | |
pPort->stLineTestPara.pstResult->vac_rg = pMlt->hazVAC.measRG; | |
pPort->stLineTestPara.pstResult->vdc_tr = pMlt->hazVDC.measTR; | |
pPort->stLineTestPara.pstResult->vdc_tg = pMlt->hazVDC.measTG; | |
pPort->stLineTestPara.pstResult->vdc_rg = pMlt->hazVDC.measRG; | |
if(TI_Outside12 == pPort->stLineTestPara.pstResult->item) | |
{ | |
StartSiLineTest(pPort, TI_LineCap); | |
} | |
else | |
{ | |
usrline_report(pPort->stLineTestPara.pstResult->port,EV_FXS_TEST_DONE,0, 0); | |
} | |
} | |
void SiSendResultCap(Port_t *pPort, ProSLICMLTType *pMlt) | |
{ | |
USLPUT2 ("RG Capacitance = %d.%d nF ***\n",pMlt->capFaults.measRG/10,pMlt->capFaults.measRG%10); | |
USLPUT2 ("TG Capacitance = %d.%d nF ***\n",pMlt->capFaults.measTG/10,pMlt->capFaults.measTG%10); | |
USLPUT2 ("TR Capacitance = %d.%d nF ***\n",pMlt->capFaults.measTR/10,pMlt->capFaults.measTR%10); | |
pPort->stLineTestPara.pstResult->cap_tr = pMlt->capFaults.measTR/10; | |
pPort->stLineTestPara.pstResult->cap_tg = pMlt->capFaults.measTG/10; | |
pPort->stLineTestPara.pstResult->cap_rg = pMlt->capFaults.measRG/10; | |
if(TI_Outside12 == pPort->stLineTestPara.pstResult->item) | |
{ | |
StartSiLineTest(pPort, TI_LineRes); | |
} | |
else | |
{ | |
usrline_report(pPort->stLineTestPara.pstResult->port, EV_FXS_TEST_DONE,0, 0); | |
} | |
} | |
void SiSendResultRes(Port_t *pPort, ProSLICMLTType *pMlt) | |
{ | |
signed long temp; | |
temp = pMlt->resFaults.measTR; | |
USLPUT2("tr = %ld.%ld Ohm\n",temp/10, temp % 10); | |
temp = pMlt->resFaults.measRG; | |
USLPUT2("rg = %ld.%ld Ohm\n",temp/10, temp % 10); | |
temp = pMlt->resFaults.measTG; | |
USLPUT2("tg = %ld.%ld Ohm\n",temp/10, temp % 10); | |
pPort->stLineTestPara.pstResult->res_tr = pMlt->resFaults.measTR/10; | |
pPort->stLineTestPara.pstResult->res_tg = pMlt->resFaults.measTG/10; | |
pPort->stLineTestPara.pstResult->res_rg = pMlt->resFaults.measRG/10; | |
usrline_report(pPort->stLineTestPara.pstResult->port, EV_FXS_TEST_DONE, 0, 0); | |
} | |
void SiSendResultDCFeedSt( Port_t *pPort ) | |
{ | |
signed long data = 0, temp = 0; | |
long long vtr = 0, iloop = 0; | |
temp = ctrl_ReadRAMWrapper(pPort->ProObj->deviceId->ctrlInterface->hCtrl,pPort->ProObj->channel,SI3217X_COM_RAM_MADC_ILOOP); | |
USLPUT2(" battary %ld.\n", temp); | |
data = ChangeData(temp); | |
iloop = data; | |
iloop = iloop * 1676; | |
USLPUT2(" iloop %lld \n", iloop); | |
data = lldivde( iloop, 1000000000); /* mA */ | |
USLPUT2(" iloop %ld \n", data); | |
pPort->stLineTestPara.pstResult->loop_curent = data; | |
temp = ctrl_ReadRAMWrapper(pPort->ProObj->deviceId->ctrlInterface->hCtrl,pPort->ProObj->channel,SI3217X_COM_RAM_VDIFF_SENSE); | |
data = ChangeData(temp); | |
vtr = data; | |
vtr = vtr * 931323; | |
USLPUT2(" Vol %lld \n", vtr); | |
data = lldivde( vtr, 1000000000 ); /* mV */ | |
USLPUT2(" Vol %ld \n", data); | |
if( 0 != pPort->stLineTestPara.pstResult->loop_curent ) | |
{ | |
pPort->stLineTestPara.pstResult->loop_res = longfabs(data/pPort->stLineTestPara.pstResult->loop_curent); | |
} | |
else | |
{ | |
pPort->stLineTestPara.pstResult->loop_res = 100000000;/* consider the res as 100M ohm */ | |
} | |
if(TI_InLoopCurrent == pPort->stLineTestPara.si_item) | |
{ | |
pPort->stLineTestPara.pstResult->loop_res = 0; | |
} | |
usrline_report(pPort->stLineTestPara.pstResult->port,EV_FXS_TEST_DONE,0,0); | |
} | |
void SiSendResultBatteryVol(Port_t *pPort) | |
{ | |
signed long data = 0, temp = 0; | |
long long vtr = 0; | |
temp = ctrl_ReadRAMWrapper(pPort->ProObj->deviceId->ctrlInterface->hCtrl,pPort->ProObj->channel,SI3217X_COM_RAM_MADC_VBAT); | |
USLPUT2(" battary %ld.%d\n", temp, sizeof(temp)); | |
data = ChangeData(temp); | |
USLPUT2(" battary %ld.\n", data); | |
vtr = data; | |
vtr = vtr * 931323; | |
USLPUT2(" vtr %lld.\n", vtr); | |
data = lldivde( vtr, 1000000000 ); /* mV */ | |
pPort->stLineTestPara.pstResult->battary = data; | |
USLPUT2(" battary %ld.\n", data); | |
usrline_report(pPort->stLineTestPara.pstResult->port, EV_FXS_TEST_DONE,0,0); | |
} | |
void SiSendResultHook( Port_t *pPort ) | |
{ | |
if( pPort->hook_state == HOOKOFF ) | |
{ | |
pPort->stLineTestPara.pstResult->user_flg = 1; | |
} | |
else | |
{ | |
pPort->stLineTestPara.pstResult->user_flg = 0; | |
} | |
usrline_report(pPort->stLineTestPara.pstResult->port,EV_FXS_TEST_DONE,0,0); | |
} | |
void SiSendResultRingtouser( Port_t *pPort ) | |
{ | |
long data = 0, vtr = 0; | |
long long temp = 0, vtr2 = 0; | |
u8 i = 0; | |
for( i = 0; i < MAX_RING_CNT; i++ ) | |
{ | |
data = ChangeData(RingVol[i]); | |
temp = data; | |
temp = temp * 931323; | |
USLPUT2("Ring[%d] = %ld, tem %lld\n", i, data, temp); | |
data = lldivde( temp, 1000000000 ); | |
USLPUT2("Ring[%d] = %ld\n", i, data); | |
vtr += data; | |
vtr2 += data; | |
} | |
USLPUT2("vtr = %ld, vtr2 = %lld\n", vtr, vtr2); | |
vtr = vtr * 1000 / MAX_RING_CNT/ 1414; | |
pPort->stLineTestPara.pstResult->ring_vol = vtr; | |
USLPUT2(" vol %ld.\n", vtr); | |
usrline_report(pPort->stLineTestPara.pstResult->port,EV_FXS_TEST_DONE,0,0); | |
} | |
void SiRen( Port_t *pPort, ProSLICMLTType *pMlt ) | |
{ | |
USLPUT2(" REN %d.\n", pMlt->ren.renValue); | |
pPort->stLineTestPara.pstResult->ren = pMlt->ren.renValue; | |
if(TI_LineConnect == pPort->stLineTestPara.pstResult->item) | |
{ | |
pPort->stLineTestPara.pstResult->user_flg = pPort->hook_state; | |
USLPUT2(" user_flg %d.\n", pPort->stLineTestPara.pstResult->user_flg); | |
} | |
usrline_report(pPort->stLineTestPara.pstResult->port,EV_FXS_TEST_DONE,0,0); | |
} | |
long ChangeData(unsigned long n) | |
{ | |
long t = 0; | |
unsigned long m = 0; | |
if( 0x1 & n>>28 ) | |
{ | |
m = (~n & 0x1fffffff) + 1; | |
t = -m; | |
} | |
else | |
{ | |
t = n; | |
} | |
return t; | |
} | |
long lldivde(long long x, long y) | |
{ | |
int s = 1; | |
long n = 0; | |
long long m = 0; | |
m = x; | |
if( m < 0 ) | |
{ | |
s = -1; | |
m = -m; | |
} | |
while(1) | |
{ | |
m = m - y ; | |
if( m < 0 ) break; | |
n++; | |
} | |
return n*s ; | |
} | |
long longfabs( long x ) | |
{ | |
if( x < 0 ) return -x; | |
return x; | |
} |