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;

+}