zte's code,first commit
Change-Id: I9a04da59e459a9bc0d67f101f700d9d7dc8d681b
diff --git a/ap/os/linux/linux-3.4.x/drivers/slic/si_adt.c b/ap/os/linux/linux-3.4.x/drivers/slic/si_adt.c
new file mode 100644
index 0000000..0fa016d
--- /dev/null
+++ b/ap/os/linux/linux-3.4.x/drivers/slic/si_adt.c
@@ -0,0 +1,2373 @@
+/***********************************************************************
+* 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;
+}