[Feature]Upload Modem source code

Change-Id: Id4294f30faced84d3e6fd6d5e61e1111bf287a37
diff --git a/mcu/driver/tty/src/dcl_tty.c b/mcu/driver/tty/src/dcl_tty.c
new file mode 100644
index 0000000..5a67ccc
--- /dev/null
+++ b/mcu/driver/tty/src/dcl_tty.c
@@ -0,0 +1,2922 @@
+/*****************************************************************************
+*  Copyright Statement:
+*  --------------------
+*  This software is protected by Copyright and the information contained
+*  herein is confidential. The software may not be copied and the information
+*  contained herein may not be used or disclosed except with the written
+*  permission of MediaTek Inc. (C) 2012
+*
+*  BY OPENING THIS FILE, BUYER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
+*  THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE")
+*  RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO BUYER ON
+*  AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL WARRANTIES,
+*  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF
+*  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NONINFRINGEMENT.
+*  NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH RESPECT TO THE
+*  SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY, INCORPORATED IN, OR
+*  SUPPLIED WITH THE MEDIATEK SOFTWARE, AND BUYER AGREES TO LOOK ONLY TO SUCH
+*  THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO. MEDIATEK SHALL ALSO
+*  NOT BE RESPONSIBLE FOR ANY MEDIATEK SOFTWARE RELEASES MADE TO BUYER'S
+*  SPECIFICATION OR TO CONFORM TO A PARTICULAR STANDARD OR OPEN FORUM.
+*
+*  BUYER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S ENTIRE AND CUMULATIVE
+*  LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE RELEASED HEREUNDER WILL BE,
+*  AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE MEDIATEK SOFTWARE AT ISSUE,
+*  OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE CHARGE PAID BY BUYER TO
+*  MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE.
+*
+*  THE TRANSACTION CONTEMPLATED HEREUNDER SHALL BE CONSTRUED IN ACCORDANCE
+*  WITH THE LAWS OF THE STATE OF CALIFORNIA, USA, EXCLUDING ITS CONFLICT OF
+*  LAWS PRINCIPLES.  ANY DISPUTES, CONTROVERSIES OR CLAIMS ARISING THEREOF AND
+*  RELATED THERETO SHALL BE SETTLED BY ARBITRATION IN SAN FRANCISCO, CA, UNDER
+*  THE RULES OF THE INTERNATIONAL CHAMBER OF COMMERCE (ICC).
+*
+*****************************************************************************/
+
+/*******************************************************************************
+ * Filename:
+ * ---------
+ *   dcl_tty.c
+ *
+ * Project:
+ * --------
+ *   MOLY
+ *
+ * Description:
+ * ------------
+ *   Define how to access COM Port. Provide API for upper-layer applications to access COM Port
+ *   It works with enabling compile flag __TTY_UT__.
+ *
+ * Author:
+ * -------
+ * -------
+ *
+ * ==========================================================================
+ * $Log$
+ *
+ * 11 03 2021 li-cheng.tsai
+ * [MOLY00629269] [FOCUS][VMOLYM][MT6298][Mercury][Pre-MP1][SQC][Dongle][MTBF][HQ][Lab][Ericsson][ErrorTimes:3][1][core0,vpe1,tc2(vpe1)] Fatal Error (0x1d, 0x0, 0x900072a8) - DHLHD
+ * 	
+ * 	[MD700.MP][MPD] patch back from VMOLYM, avoid race condition caused null callback function issue.
+ *
+ * 08 27 2021 li-cheng.tsai
+ * [MOLY00711608] [WIN] MiniDump is observed during ICT S4(Hibernate) stress.
+ * 	
+ * 	[MD700.MP][MPD] Solved race condition in assign rx ior
+ *
+ * 09 18 2020 li-cheng.tsai
+ * [MOLY00569647] [MP7.PRECHECKIN.DEV][Code sync] sync code from T700
+ * [R3.MP][MPD][CCCIDEV]code sync from T700
+ *
+ * 09 15 2020 li-cheng.tsai
+ * [MOLY00569647] [MP7.PRECHECKIN.DEV][Code sync] sync code from T700
+ * [MP7.PRECHECKIN.DEV][MPD][CCCIDEV]code sync from T700
+ *
+ * 09 14 2020 i-wei.tsai
+ * [MOLY00548843] [TITAN CRASH][Wingtech][TITAN][MT6765][N21][TFN][P200722-00292 ]S215DL-11 Device crashes into CP Crash upload mode
+ * .
+ *
+ * 08 10 2020 i-wei.tsai
+ * [MOLY00548843] [TITAN CRASH][Wingtech][TITAN][MT6765][N21][TFN][P200722-00292 ]S215DL-11 Device crashes into CP Crash upload mode
+ * 	
+ * 	. skip clear tx handling for ccci port
+ *
+ * 06 01 2020 li-cheng.tsai
+ * [MOLY00526500] [MODEM][ASSERT ][ASSERT] file:mcu/service/qmu_bm/src/qmu_bm.c line:512 p1:0x00000000 p2:0x00000000 p3:0x00000000
+ * CCCI TTY change to fix error handling
+ *
+ * 12 05 2019 i-wei.tsai
+ * [MOLY00463962] [Gen97] TTY DEV
+ * 	
+ * 	.
+ *
+ * 12 04 2019 amit.singh
+ * [MOLY00463020] [IPCORE] [TTY] VMOLY Patchback memory reduction by re-arranging member fields of structures
+ * 	
+ * 	TTY memory reduction by structure rearrange.
+ *
+ * 12 02 2019 amit.singh
+ * [MOLY00454015] [TTY] LG patchabck of MOLY00394195 to VMOLY.1001.DEV
+ * 	
+ * 	1001.DEV to VMOLY TRUNK patchback TTY.
+ *
+ * 06 18 2019 i-wei.tsai
+ * [MOLY00413678] [MT6297][Apollo][Ericsson][IODT][NSA FullStack][Kista][5G][1][core0,vpe0,tc0(vpe0)] Assert fail dcl_tty.c 1063 - DR
+ * 	
+ * 	.remove un-used assertion
+ *
+ * 09 11 2018 i-wei.tsai
+ * [MOLY00349664] [ASSERT] file:mcu/common/driver/tty/src/dcl_tty.c line:1789
+ * 	
+ * 	.fix race condition issue in rx callback
+ *
+ * 07 24 2018 i-wei.tsai
+ * [MOLY00341790] [MT6295] UDC feature patch back
+ * 	
+ * 	.change spinlock to HWITC
+ *
+ * 06 04 2018 i-wei.tsai
+ * [MOLY00331344] [Gen95] TTYCore fix
+ * 	
+ * 	.
+ *
+ * 09 18 2017 i-wei.tsai
+ * [MOLY00278689] Performance improvement of INT_QueryExceptionStatus
+ * 	
+ * 	.
+ *
+ * 07 06 2017 i-wei.tsai
+ * [MOLY00262251] [Coverity defect fix] tty coverity fix
+ * .
+ *
+ * 05 09 2017 i-wei.tsai
+ * [MOLY00248066] [Gen93] [TTY] Log format refine
+ * .
+ * 	fix modis build error
+ *
+ * 05 09 2017 i-wei.tsai
+ * [MOLY00248066] [Gen93] [TTY] Log format refine
+ * .
+ * 	fix modis warning
+ *
+ * 05 09 2017 i-wei.tsai
+ * [MOLY00248066] [Gen93] [TTY] Log format refine
+ * .
+ * 	remove dummy character
+ *
+ * 05 09 2017 i-wei.tsai
+ * [MOLY00248066] [Gen93] [TTY] Log format refine
+ * .
+ * 	TTY log refine
+ *
+ * 06 22 2016 mt.tsai
+ * [MOLY00154662] Fix the tty build warning
+ * .delete unused variable in TTY
+ *
+ * 06 22 2016 mt.tsai
+ * [MOLY00177032] [Coverity Scanned Code Defect]CID:116560 code defect happened in /mcu/common/driver/tty/src/dcl_tty.c
+ * .
+ * [Coverity] add spinlock to full fill the protection of some variables
+ *
+ * 02 26 2016 mt.tsai
+ * [MOLY00166612] Remove violation include kal_debug.h
+ * The APIs in kal_debug.h is legacy and don't be provided for user
+ *
+ * 09 30 2015 mt.tsai
+ * [MOLY00143135] [UMOLY][LR11] TTYCore Unit Test
+ * .modified files for ttycore unit test
+ *
+ * 09 15 2015 i-wei.tsai
+ * [MOLY00141929] [UMOLY][ELBRUS][TTY] Add SMP support
+ * 	.
+ *
+ * 03 02 2015 i-wei.tsai
+ * [MOLY00097392] [UMOLY] [TTY] Timer tick macro modification
+ * 	.
+ *
+ * 12 10 2014 i-wei.tsai
+ * [MOLY00086663] [TK6291] [TTY] Add new uart port for MTAD
+ * 	.
+ *
+ * 11 14 2014 i-wei.tsai
+ * [MOLY00084437] [UMOLY] [TTY] rollback changes
+ * 	.
+ *
+ * 06 16 2014 i-wei.tsai
+ * [MOLY00068713] [MT6752] MD2 uart config setting (Buffer mode)
+ * 	.
+ *
+ * 04 25 2014 i-wei.tsai
+ * [MOLY00063770] [Rose][KK][Free Test][EE][VT Call]EE about [ASSERT] file:dcl_tty.c line:1367 will pop up after tap "Use touch tone keypad" to enter VT call screen.
+ * 	.
+ *
+ * 03 12 2014 i-wei.tsai
+ * [MOLY00059311] [TTY] New Feature for configurable indication mechanism
+ *
+ * 10 29 2013 i-wei.tsai
+ * [MOLY00044179] [TTY] Fixed 82LTE VT issue
+ * 	.
+ *
+ * 09 13 2013 shenghui.shi
+ * [MOLY00035078] [MT6290][PDN] Enable GDMA & HDMA related module PDN support
+ * move uart pdn_clr from dcl_tty.c to uart.c
+ *
+ * 08 26 2013 shenghui.shi
+ * [MOLY00035212] fix uart build modis error
+ * .
+ *
+ * 08 26 2013 shenghui.shi
+ * [MOLY00035078] [MT6290][PDN] Enable GDMA & HDMA related module PDN support
+ * add uart PDN feature
+ *
+ * 06 26 2013 i-wei.tsai
+ * [MOLY00027496] [TTYCore] Features check-in
+ * 1. add new TTY_CMD_MTU_SIZE support
+ * 2. add plug-in/plug-out indication
+ * 3. fix issue of flushing rx internal gpd
+ *
+ * 06 19 2013 i-wei.tsai
+ * [MOLY00026667] [TTYCore] Revise ttycore trace log in exception mode
+ *
+ * 05 29 2013 haoren.kao
+ * [MOLY00024108] Support New USB Core
+ * Replace with New USB Core.
+ * We sync with the following codes from HaoRen MOLY CBr w1322:
+ * 1. USB Core
+ * 2. USB Class - acm/rndis/mbim
+ * 3. ipcore
+ * 4. ttycore
+ * 5. ethercore
+ *
+ * 05 15 2013 i-wei.tsai
+ * [MOLY00021838] [MT6290 Bring-up] TTY DEV.
+ * Turn off aggressive log trace
+ *
+ * 05 10 2013 i-wei.tsai
+ * [MOLY00021838] [MT6290 Bring-up] TTY DEV
+ * sync from MT6290E1 First Call Branch
+ *
+ * 05 10 2013 i-wei.tsai
+ * [MOLY00021376] [MT6290 Bring-up] Basic load
+ * Check-in support
+ *
+ * 05 09 2013 i-wei.tsai
+ * [MOLY00021838] [MT6290 Bring-up] TTY DEV
+ * fix error for setting tx not rdy flag
+ *
+ * 05 09 2013 i-wei.tsai
+ * [MOLY00021838] [MT6290 Bring-up] TTY DEV
+ * add sending Ready2Write message when dirver attach
+ *
+ * 05 08 2013 i-wei.tsai
+ * [MOLY00021838] [MT6290 Bring-up] Revise ttycore trace log
+ * .
+ *
+ * 05 03 2013 i-wei.tsai
+ * [MOLY00021396] [MT6290 Bring-up] [Basic Load Support] [TTYCore] add option __MAUI_BASIC__
+ * basic load support
+ *
+ * 03 08 2013 i-wei.tsai
+ * [MOLY00011358] [TTYCore] TTYCore support
+ * Add CCIF UART device type and modify comments
+ *
+ * 03 01 2013 i-wei.tsai
+ * [MOLY00010632] add TTYCore new features
+ * fixed typo
+ *
+ * 02 21 2013 i-wei.tsai
+ * [MOLY00010632] add TTYCore new features
+ * checkin supporting buffer port features
+ *
+ * 11 08 2012 haoren.kao
+ * [MOLY00005322] TATAKA merge to MOLY
+ * 
+ * MOLY Migration from TATAKA
+ ****************************************************************************/
+
+#include <stdio.h>
+#include "dcl.h"
+
+#include "qbm_config_num.h"
+#include "qmu_bm.h"
+#include "qmu_bm_util.h"
+#include "kal_public_api.h"
+#include "kal_general_types.h"
+#include "stack_ltlcom.h"
+#include "hif_ior.h"
+#include "kal_internal_api.h"
+#include "devdrv_ls.h"
+#include "drv_msgid.h"
+#include "md_drv_sap.h"
+#include "drvpdn.h"
+#include "drv_gdma.h"
+#include <ex_public.h>
+#include "kal_hrt_api.h"
+
+#include "cccidev_qbm.h"  /* macros for QBM_TYPE_CCCI_COMM */
+
+//for reference the vp number
+#include "cmux_vp_num.h"
+
+#define TTY_CONSOLE_TRACE_ENABLED 0
+
+#define TTY_AGGRESSIVE_TRACE  0
+
+/*20120724 Ian Modify CCCI_COMM for TTYCore*/
+//  #if __HIF_CCCI_SUPPORT__
+//  /* using CCCI_COMM type to replace QBM_TYPE_TTY_INT/QBM_TYPE_TTY_TYPE1/QBM_TYPE_TTY_TYPE2 */
+//  #define TTY_QBM_DATA_LEN            QBM_CCCI_COMM_DATA_LEN
+//  #define TTY_QBM_DATA_TYPE           QBM_TYPE_CCCI_COMM
+//  #define TTY_QBM_DES_GET_DATAPTR     CCCIDEV_GET_QBM_DATAPTR
+//  #define TTY_QBM_DES_GET_DATALEN     CCCIDEV_GET_QBM_DATALEN
+//  #define TTY_QBM_DES_SET_DATALEN     CCCICOMM_SET_QBM_DATALEN
+//  #else
+//  #define TTY_QBM_DATA_LEN            QBM_TTY_XXX_DATA_LEN
+//  #define TTY_QBM_DATA_TYPE           QBM_TYPE_TTY_INT
+//  #define TTY_QBM_DES_GET_DATAPTR     QBM_DES_GET_DATAPTR
+//  #define TTY_QBM_DES_GET_DATALEN     QBM_DES_GET_DATALEN
+//  #define TTY_QBM_DES_SET_DATALEN     QBM_DES_SET_DATALEN
+//  #endif
+
+extern void dbg_print(char *fmt,...);
+
+#if TTY_CONSOLE_TRACE_ENABLED==1
+    /*
+     * Print indexed trace to console.
+     */
+    #if defined(__MTK_TARGET__)
+        //#define tty_console_trace dbg_print
+        #define tty_console_trace dbg_print
+        #define TTY_NEW_LINE "\r\n"
+    #else
+        #define tty_console_trace dbg_print
+        #define TTY_NEW_LINE "\n"
+    #endif
+
+/*    #define tty_trace_error(...) tty_console_trace(__VA_ARGS__)*/
+/*    #define tty_trace_info(...)  tty_console_trace(__VA_ARGS__)*/
+
+    #define BEGIN_TRACE_MAP(_mod)
+    #define TRC_MSG(_msg_index, _fmt) static const char _msg_index [] = _fmt TTY_NEW_LINE;
+    #define END_TRACE_MAP(_mod)
+#else
+    /*
+     * Use DHL logging.
+     */
+    #ifndef __MAUI_BASIC__
+/*        #define tty_trace_error(...)                                          \
+            do{                                                               \
+                if(INT_QueryExceptionStatus() == KAL_FALSE)                   \
+                {                                                             \
+                    dhl_trace(TRACE_ERROR, DHL_USER_FLAG_NONE, __VA_ARGS__);  \
+                }                                                             \
+            }while(0)*/
+            
+/*        #define tty_trace_info(...)                                           \
+            do{                                                               \
+                if(INT_QueryExceptionStatus() == KAL_FALSE)                   \
+                {                                                             \
+                    dhl_trace(TRACE_INFO, DHL_USER_FLAG_NONE, __VA_ARGS__);   \
+                }                                                             \
+            }while(0)*/
+            
+/*        #define tty_trace_func(...)                                           \
+            do{                                                               \
+                if(INT_QueryExceptionStatus() == KAL_FALSE)                   \
+                {                                                             \
+                    dhl_trace(TRACE_FUNC, DHL_USER_FLAG_NONE, __VA_ARGS__);   \
+                }                                                             \
+            }while(0)*/
+    #else
+/*        #define tty_trace_error(...)*/
+/*        #define tty_trace_info(...)*/
+/*        #define tty_trace_func(...)*/
+    #endif
+#endif /* TTY_CONSOLE_TRACE_ENABLED */
+
+#ifndef __MAUI_BASIC__
+#include "tty_trace.h"
+#endif
+
+/* Macros */
+/* ==================================================================================================== */
+#ifdef ATEST_SYS_TTYCORE
+    extern kal_bool ut_assert_flag;
+
+    #ifdef ASSERT
+    #undef ASSERT
+    #endif
+    //#define ASSERT(x) do{ if (x) ut_assert_flag = KAL_TRUE; }while(0)
+    void ASSERT(int x) {
+        if (!x) {
+            ut_assert_flag = KAL_TRUE;
+        }
+    }
+#endif
+#define VAR_MSG_ASSERT(var_msg) do{int var_msg=0; ASSERT(var_msg);} while(0)
+
+#ifdef __TTY_DBG_MODE__
+#define DBG_ASSERT(expr)    ASSERT(expr)
+#define TTY_CHECK_CONTEXT_ENABLED 1
+#else
+#define DBG_ASSERT(expr)
+#define TTY_CHECK_CONTEXT_ENABLED 0
+#endif
+
+#define TTY_HWITC_ENABLE (1)
+#if defined(TTY_HWITC_ENABLE)
+  #define TTY_SPIN_LOCK(_s) kal_hrt_take_itc_lock(KAL_ITC_TTY, KAL_INFINITE_WAIT)
+  #define TTY_SPIN_UNLOCK(_s) kal_hrt_give_itc_lock(KAL_ITC_TTY)
+#else
+  #define TTY_SPIN_LOCK(_s) kal_take_spinlock(_s, KAL_INFINITE_WAIT)
+  #define TTY_SPIN_UNLOCK(_s) kal_give_spinlock(_s)
+#endif
+
+#define TTY_CHECK_HANDLE(handle) \
+    do{ \
+        if (handle == STATUS_INVALID_DEVICE) {return STATUS_FAIL;} \
+        if (!DCL_UART_IS_HANDLE_MAGIC(handle)) {if(INT_QueryExceptionStatus() == KAL_FALSE) \
+MD_TRC(TTY_TR_INVALID_HANDLE,__LINE__, handle, kal_get_active_module_id());return STATUS_INVALID_DCL_HANDLE;} \
+    }while(0)
+
+#define TTY_CHECK_DEV_IS_READY(dev) \
+    do{ \
+        /* Check if the driver callback is registered */ \
+        if (dev >= UART_DEV_CNT || dev < 0 || !tty_mgmt_info[dev].active) \
+        { \
+            if(INT_QueryExceptionStatus() == KAL_FALSE) \
+MD_TRC(TTY_TR_DEV_DRV_NOT_RDY,__LINE__, dev, kal_get_active_module_id()); \
+            return STATUS_DEVICE_NOT_EXIST; \
+        } \
+    }while(0)
+
+#define TTY_CHECK_DEV_VALID(dev) \
+            do{ \
+                if (dev >= UART_DEV_CNT || dev < 0) {if(INT_QueryExceptionStatus() == KAL_FALSE) \
+MD_TRC(TTY_TR_DEV_NOT_VALID,__LINE__, dev, kal_get_active_module_id());return STATUS_INVALID_DEVICE;} \
+            }while(0)
+
+#if TTY_CHECK_CONTEXT_ENABLED==1
+#define TTY_CHECK_RUN_IN_HISR(dev) do{if (tty_mgmt_info[dev].owner_id != MOD_DRV_DBG/*dbg_print is exception*/ && kal_if_hisr()){VAR_MSG_ASSERT(TTY_it_runs_in_hisr);}} while(0)
+#define TTY_CHECK_ACTIVE_MOD(dev) \
+    do{ \
+        if (tty_mgmt_info[dev].owner_id != MOD_DRV_DBG/*dbg_print is exception*/ \
+            && tty_mgmt_info[dev].owner_id != MOD_DHL \
+            && tty_mgmt_info[dev].owner_id != MOD_DHL_READER \
+            && tty_mgmt_info[dev].opened \
+            && tty_mgmt_info[dev].owner_id != kal_get_active_module_id()) { \
+            VAR_MSG_ASSERT(TTY_Active_module_id_not_match); \
+        } \
+    }while(0)
+#else
+#define TTY_CHECK_RUN_IN_HISR(dev)
+#define TTY_CHECK_ACTIVE_MOD(dev)
+#endif
+
+#define TTY_CONV_FLUSH_TX(cnt_thre) \
+    count = 0; \
+    if (TTY_IS_CONVENTIONAL_TX(device)) { \
+        while (1) { \
+            if (tty_mgmt_info[device].tx_gpd_num_used == 0) { \
+                break; \
+            } \
+            kal_sleep_task(KAL_TICKS_10_MSEC/2); \
+            if (++count > cnt_thre) { \
+                VAR_MSG_ASSERT(flush_tx_cmd_too_long); \
+            } \
+        } \
+    }
+
+#define TTY_CONV_FLUSH_RX(cnt_thre) \
+    count = 0; \
+    if (TTY_IS_CONVENTIONAL_RX(device)) { \
+        while (1) { \
+            if (tty_mgmt_info[device].rx_gpd_num_assigned == 0) { \
+                break; \
+            } \
+            kal_sleep_task(KAL_TICKS_10_MSEC/2); \
+            if (++count > cnt_thre) { \
+                VAR_MSG_ASSERT(flush_rx_cmd_too_long); \
+            } \
+        } \
+    }
+
+
+
+#define TTY_IS_CONVENTIONAL_TX(dev) (!(tty_mgmt_info[dev].flag & TTY_FLAG_NEW_TX))
+#define TTY_IS_CONVENTIONAL_RX(dev) (!(tty_mgmt_info[dev].flag & TTY_FLAG_NEW_RX))
+#define TTY_DRV_IS_ATTACHED(dev)    (tty_mgmt_info[dev].drv_state == DRV_ST_ATTACHED)
+
+#define DCL_UART_MAGIC_NUM  0x40000000
+#define DCL_UART_IS_HANDLE_MAGIC(handl_) ((handl_)& DCL_UART_MAGIC_NUM)
+#define DCL_UART_GET_DEV(handle_) ((DCL_DEV)((handle_) & (~DCL_UART_MAGIC_NUM)))
+
+#define UART_DEV_CNT  (uart_max_port - uart_port1 + 1) //subtract uart1, in case uart1 != 0 in future.
+
+#define TTY_BC_TX_GPD_MAX_NUM       2   /* Tx Max GPD number for backward-compatible */
+#define GPD_NUM_FOR_TTY     100
+
+#if 0
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+#endif
+
+#define TTY_IS_BUFF_PORT(dev) ((tty_mgmt_info[dev].drv_type == BUFF_DRV_TYPE))  
+#define TTY_MIN(_a, _b) (((_a) <= (_b)) ? (_a) : (_b))
+
+#define TTY_CHK_DEV_OPEN(dev) (DCL_TRUE == tty_mgmt_info[dev].opened)
+
+/* Structure define & Global variable */
+/* ==================================================================================================== */
+typedef struct _tty_port_mgmt
+{
+    /* for buffer type driver*/
+    DCL_UINT32 drv_type;
+    kal_spinlockid spinLock;         // each device has its own lock
+    DCL_UINT32 rx_allow_len;         //Indicates downlink mtu size of HIF
+    qbm_gpd *rx_gpd;
+    DCL_UINT32 rx_gpd_num_assigned;
+    DCL_UINT32 tx_gpd_num_used;
+    /* for backward-compatible */
+    DCL_UART_TX_FUNC conv_tx_cb;
+    DCL_UART_RX_FUNC conv_rx_cb;
+    DCL_UINT32 dev_type;             //record device type
+    DCL_UINT32 qbm_data_len;         //supported GPD type length
+    DCL_UINT32 flag;
+    tty_drv_state_change_cb drv_state_change_cb;
+    DCL_UINT32 qbm_data_type;        //supported GPD type
+    tty_rx_cb rx_cb;
+    tty_txdone_cb tx_done_cb;
+    SeriPort_HANLDER_CB sp_handler_cb;
+
+    module_type pending_owner;
+    DCL_UINT16 rx_buf_offset;        // it indicates the buffer offset of rx_gpd (data in rx_gpd before offset has been received)
+    DCL_UINT16 chunk_size;
+    module_type owner_id;
+
+    tty_drv_state_e drv_state;       // 1: driver attach; 0: driver detach
+    /* For legacy USBcore solution: driver attach event may be later than user traffic*/
+    DCL_BOOL tx_not_rdy;
+    DCL_BOOL opened;                 // opened by upper module
+    DCL_BOOL init_by_new_mod;
+    DCL_BOOL rx_up_mod_wait;         //add for buffer device
+    DCL_BOOL tx_up_mod_wait;
+    DCL_BOOL flush_rx;
+    DCL_BOOL flush_tx;
+    DCL_BOOL no_indication;          //User can set attribute to disable receiving ILM through SIO_SET_INDICATION
+    DCL_BOOL active;                 // registered uart handler callback by driver
+    /*store flag if user send SIO_CMD_OPEN or register callback before driver register CB*/
+    DCL_BOOL early_tx_done_cb_req;
+    DCL_BOOL early_open_req;
+} tty_port_mgmt;
+
+typedef enum
+{
+    GPD_DRV_TYPE,
+    BUFF_DRV_TYPE,
+}tty_driver_type;
+
+typedef struct _tty_dev_info
+{
+    SIO_TYPE_T dev_type;
+    DCL_UINT32 buff_type;
+    DCL_UINT32 buff_data_len;
+    tty_driver_type drv_type;
+}tty_dev_info;
+
+#define NOT_DEFINED_TYPE 0xFFFFFFFF
+#define NOT_DEFINED_LENGTH 0xFFFFFFFF
+
+static tty_dev_info tty_dev_info_tbl[DCL_UART_DEV_TYPE_MAX] = {
+#if defined(MT6752) && defined(__MD2__)
+    {DCL_UART_TYPE,             QBM_TYPE_TTY_INT  ,     QBM_TTY_XXX_DATA_LEN    ,   BUFF_DRV_TYPE},     //6752 MD2 uart only support buffer mode
+#else
+    {DCL_UART_TYPE,             QBM_TYPE_TTY_INT  ,     QBM_TTY_XXX_DATA_LEN    ,   GPD_DRV_TYPE},
+#endif 
+    {DCL_UART_USB_TYPE,         QBM_TYPE_TTY_INT  ,     QBM_TTY_XXX_DATA_LEN    ,   GPD_DRV_TYPE},
+    {DCL_UART_BLUETOOTH_TYPE,   QBM_TYPE_TTY_INT  ,     QBM_TTY_XXX_DATA_LEN    ,   BUFF_DRV_TYPE},     //not checked
+    {DCL_UART_SPPA_TYPE,        QBM_TYPE_TTY_INT  ,     QBM_TTY_XXX_DATA_LEN    ,   BUFF_DRV_TYPE},     //not checked
+    {DCL_UART_CMUX_TYPE,        NOT_DEFINED_TYPE  ,     NOT_DEFINED_LENGTH      ,   BUFF_DRV_TYPE},    
+    {DCL_UART_CCCI_TYPE,        QBM_TYPE_CCCI_COMM,     QBM_CCCI_COMM_DATA_LEN  ,   GPD_DRV_TYPE},
+    {DCL_UART_CCIF_TYPE,        NOT_DEFINED_TYPE,       NOT_DEFINED_LENGTH      ,   BUFF_DRV_TYPE},
+    {DCL_UART_DCC_TYPE,         QBM_TYPE_TTY_INT  ,     QBM_TTY_XXX_DATA_LEN    ,   BUFF_DRV_TYPE},     //not checked
+    {DCL_UART_LOGACC_TYPE,      QBM_TYPE_TTY_INT  ,     QBM_TTY_XXX_DATA_LEN    ,   BUFF_DRV_TYPE},     //not checked
+    {DCL_UART_LMU_TYPE,         QBM_TYPE_TTY_INT  ,     QBM_TTY_XXX_DATA_LEN    ,   BUFF_DRV_TYPE},     //not checked
+    {DCL_UART_SP_USB_TYPE,      QBM_TYPE_TTY_INT  ,     QBM_TTY_XXX_DATA_LEN    ,   BUFF_DRV_TYPE},     //not checked
+    {DCL_UART_MINI_LOG_TYPE,    QBM_TYPE_TTY_INT  ,     QBM_TTY_XXX_DATA_LEN    ,   BUFF_DRV_TYPE},     //not checked
+    {DCL_UART_MTAD_TYPE,        QBM_TYPE_TTY_INT  ,     QBM_TTY_XXX_DATA_LEN    ,   GPD_DRV_TYPE},
+};
+
+
+static tty_port_mgmt tty_mgmt_info[UART_DEV_CNT];
+
+/* Internal used API declaration */
+/* ==================================================================================================== */
+static DCL_STATUS _DclSerialPort_UpModuleReinit(DCL_DEV device, module_type module_id, int flag);
+static DCL_STATUS _DclSerialPort_UpModuleRegisterCb(DCL_DEV device, tty_rx_cb rx_cb, tty_txdone_cb tx_done_cb, tty_drv_state_change_cb drv_state_change_cb);
+
+
+/* Internal used API */
+/* ==================================================================================================== */
+static void DEVDRV_LS_DRAM_EX_ROCODE 
+TTY_QBM_DES_SET_DATALEN(void* gpd, kal_uint32 data_len)
+{
+    void* bd = NULL;
+
+    ASSERT(NULL != gpd);
+    if(0 != QBM_DES_GET_BDP(gpd))
+    {
+        //4 <case> GPD->BD->BUFF
+        bd = QBM_DES_GET_DATAPTR(gpd);
+        ASSERT(NULL!=bd);
+        QBM_DES_SET_DATALEN(bd, data_len);
+        qbm_cal_set_checksum((kal_uint8 *)bd);
+    }
+
+    QBM_DES_SET_DATALEN(gpd, data_len);
+    qbm_cal_set_checksum((kal_uint8 *)gpd);
+}
+
+static DCL_UINT32 DEVDRV_LS_DRAM_EX_ROCODE 
+TTY_QBM_DES_GET_DATALEN(void* gpd)
+{
+    void* bd = NULL;
+    DCL_UINT32 data_len = 0;
+
+    ASSERT(NULL!=gpd);
+    if(0 != QBM_DES_GET_BDP(gpd)){
+        //4 <case 1> GPD->BD->BUFF
+        bd = QBM_DES_GET_DATAPTR(gpd);
+        ASSERT(NULL!=bd);
+        data_len = QBM_DES_GET_DATALEN(bd);
+    }else{
+        //4 <case 2> GPD->BUFF
+        data_len = QBM_DES_GET_DATALEN(gpd);
+    }
+    return data_len;
+}
+
+static void* DEVDRV_LS_DRAM_EX_ROCODE
+TTY_QBM_DES_GET_DATAPTR(void* gpd)
+{
+    void* bd = NULL;
+    void* data_ptr = NULL;
+    
+    ASSERT(NULL!=gpd);
+    if(0 != QBM_DES_GET_BDP(gpd)){
+        //4 <case 1> GPD->BD->BUFF
+        bd = QBM_DES_GET_DATAPTR(gpd);
+        ASSERT(NULL!=bd);
+        data_ptr = QBM_DES_GET_DATAPTR(bd);
+    }else{
+        //4 <case 2> GPD->BUFF        
+        data_ptr = QBM_DES_GET_DATAPTR(gpd);
+    }
+
+    ASSERT(NULL!=data_ptr);
+    return data_ptr;
+}
+
+static void DEVDRV_LS_DRAM_EX_ROCODE
+_tty_update_buff_info_from_port(DCL_DEV device, SIO_TYPE_T dev_type)
+{
+    DCL_UINT8 i;
+
+    for( i = 0; i < DCL_UART_DEV_TYPE_MAX; i++)
+    {
+        if(tty_dev_info_tbl[i].dev_type == dev_type)
+        {
+            tty_mgmt_info[device].qbm_data_type = tty_dev_info_tbl[i].buff_type;
+            tty_mgmt_info[device].qbm_data_len = tty_dev_info_tbl[i].buff_data_len;
+            tty_mgmt_info[device].drv_type = tty_dev_info_tbl[i].drv_type;
+            return;
+        }
+    }
+    ASSERT(i < DCL_UART_DEV_TYPE_MAX);
+    return; 
+}
+
+void DEVDRV_LS_DRAM_EX_ROCODE
+_tty_send_ilm(
+    DCL_DEV             device,
+    module_type         source_id,
+    msg_type            msg_id)
+{
+    void *port_ptr = 0;
+
+    /*New feature: some ports may not need ilm indication*/
+    if(tty_mgmt_info[device].no_indication == 1)
+    {
+        return;
+    }
+
+    switch(msg_id)
+    {
+        case MSG_ID_UART_READY_TO_READ_IND:
+            {
+                uart_ready_to_read_ind_struct *tmp;    
+                tmp = (uart_ready_to_read_ind_struct *)
+                   construct_local_para(sizeof(uart_ready_to_read_ind_struct),TD_UL);
+                tmp->port = device;
+                port_ptr = tmp;
+            }
+            break;
+        case MSG_ID_UART_READY_TO_WRITE_IND:
+            {
+                uart_ready_to_write_ind_struct *tmp;
+                tmp = (uart_ready_to_write_ind_struct *)
+                construct_local_para(sizeof(uart_ready_to_write_ind_struct),TD_UL);
+                tmp->port = device;
+                port_ptr = tmp;
+            }
+            break;
+        case MSG_ID_UART_DSR_CHANGE_IND:
+            {
+                uart_dsr_change_ind_struct *tmp;
+                tmp = (uart_dsr_change_ind_struct *)
+                construct_local_para(sizeof(uart_dsr_change_ind_struct),TD_UL);
+                tmp->port = device;
+                port_ptr = tmp;
+            }
+            break;
+        case MSG_ID_UART_ESCAPE_DETECTED_IND:
+            {
+                uart_escape_detected_ind_struct *tmp;
+                tmp = (uart_escape_detected_ind_struct *)
+                construct_local_para(sizeof(uart_escape_detected_ind_struct),TD_UL);
+                tmp->port = device;
+                port_ptr = tmp;
+            }
+            break;
+        case MSG_ID_UART_PLUGOUT_IND:
+            {
+                uart_plugout_ind_struct *tmp;
+                tmp = (uart_plugout_ind_struct *)
+                construct_local_para(sizeof(uart_plugout_ind_struct),TD_RESET);
+                tmp->port = device;
+                port_ptr = tmp;
+            }
+            break;
+        case MSG_ID_UART_PLUGIN_IND:
+            {
+                uart_plugin_ind_struct *tmp;
+                tmp = (uart_plugin_ind_struct *)
+                construct_local_para(sizeof(uart_plugin_ind_struct),TD_RESET);
+                tmp->port = device;
+                port_ptr = tmp;
+            }
+            break;
+        default:
+            {
+                /* Print error log */
+                return;
+            }
+    }
+
+    msg_send5(source_id,                           // source module ID
+                 tty_mgmt_info[device].owner_id,   // destination module ID
+                 DRIVER_PS_SAP,                    // sap ID
+                 msg_id,                           // msg ID
+                 port_ptr                          // local_para_struct *
+                 );
+
+}
+
+#ifdef __TTY_DBG_MODE__
+/**
+ *  @brief      Check if any gpd length is zero
+ *  @result     none
+ */
+static void DEVDRV_LS_DRAM_EX_ROCODE
+_tty_gpd_zero_len_check(
+    tty_io_request_t    *ior)
+{
+    tty_io_request_t *ior_tmp = ior;
+
+    do {
+        void *gpd = ior_tmp->first_gpd;
+
+        while (gpd != ior_tmp->last_gpd) {
+            ASSERT(TTY_QBM_DES_GET_DATALEN(gpd));
+            gpd = QBM_DES_GET_NEXT(gpd);
+        }
+        ASSERT(TTY_QBM_DES_GET_DATALEN(gpd));
+    } while ((ior_tmp = ior_tmp->next_request) != NULL);
+}
+#endif
+
+/**
+ *  @brief      Free all gpds of ior
+ *  @result     total number of free gpd
+ */
+static DCL_UINT32 DEVDRV_LS_DRAM_EX_ROCODE
+_tty_free_ior(
+    tty_io_request_t    *ior)
+{
+    DCL_UINT32 number = 0;
+
+    if (ior) {
+        do {
+            number += qbmt_dest_q(ior->first_gpd, ior->last_gpd);
+        } while ((ior = ior->next_request) != NULL);
+    }
+
+    return number;
+}
+
+/*
+    _tty_rx_cb is used for backward-compatible.
+    In TTY Core design, only one rx ior is prepared for Rx receiving in conventional Rx mode.
+    If rx_gpd is callbacked and when conventional upper module send SIO_CMD_GET_BYTES command to receive data, _tty_rx_cb won't be called until the only
+    one rx_gpd is re-assigned to driver.
+    Thus rx_gpd don't need mutex protection.
+*/
+DCL_STATUS DEVDRV_LS_DRAM_EX_ROCODE
+_tty_rx_cb(
+    DCL_HANDLE          handle,
+    module_type         source_id,
+    tty_io_request_t    *rx_ior)
+{
+    DCL_DEV device;
+    void *gpd_tmp;
+    tty_io_request_t *ior_tmp;
+
+    device = DCL_UART_GET_DEV(handle);
+
+    if (!tty_mgmt_info[device].flush_rx) {
+        /* global rx gpd must be NULL when rx callback of non-flush command is called */
+        ASSERT(!tty_mgmt_info[device].rx_gpd);
+    }
+
+    /* 
+        The rx callback is called by flush done :
+        <1> there is a next request of rx_ior
+        <2> there are 2 gpd of rx_ior
+    */
+    if (rx_ior->next_request)
+    {
+        ASSERT(tty_mgmt_info[device].flush_rx);
+        ASSERT(rx_ior->first_gpd == rx_ior->last_gpd);
+        ASSERT(rx_ior->next_request->first_gpd == rx_ior->next_request->last_gpd);
+        ior_tmp = rx_ior->next_request;
+        rx_ior->next_request = NULL;
+        QBM_FREE_ONE(ior_tmp->first_gpd);
+        TTY_SPIN_LOCK(tty_mgmt_info[device].spinLock);
+        ASSERT(tty_mgmt_info[device].rx_gpd_num_assigned >= 1);
+        tty_mgmt_info[device].rx_gpd_num_assigned --;
+        TTY_SPIN_UNLOCK(tty_mgmt_info[device].spinLock);
+    } else if (rx_ior->first_gpd != rx_ior->last_gpd)
+    {
+        ASSERT(tty_mgmt_info[device].flush_rx);
+
+        // tj.chang, 2011/12/27: We should not promise the length of last_gpd is 0.
+//      ASSERT(TTY_QBM_DES_GET_DATALEN(rx_ior->last_gpd) == 0);
+        ASSERT(QBM_DES_GET_NEXT(rx_ior->first_gpd) == rx_ior->last_gpd);
+        gpd_tmp = rx_ior->last_gpd;
+        rx_ior->last_gpd = rx_ior->first_gpd;
+        QBM_FREE_ONE(gpd_tmp);
+        TTY_SPIN_LOCK(tty_mgmt_info[device].spinLock);
+        ASSERT(tty_mgmt_info[device].rx_gpd_num_assigned >= 1);
+        tty_mgmt_info[device].rx_gpd_num_assigned --;
+        TTY_SPIN_UNLOCK(tty_mgmt_info[device].spinLock);
+    }
+    
+    if (!tty_mgmt_info[device].flush_rx && TTY_QBM_DES_GET_DATALEN(rx_ior->first_gpd) > 0)
+    {
+        TTY_SPIN_LOCK(tty_mgmt_info[device].spinLock);
+        tty_mgmt_info[device].rx_gpd = rx_ior->first_gpd;
+        TTY_SPIN_UNLOCK(tty_mgmt_info[device].spinLock);
+        
+        //change start for ALPS04065656
+        //handling race condition between UL data gpd and clr rx buff. 
+        if(tty_mgmt_info[device].flush_rx) {
+            void *rx_gpd;
+            TTY_SPIN_LOCK(tty_mgmt_info[device].spinLock);
+            if(tty_mgmt_info[device].rx_gpd) {
+                rx_gpd = tty_mgmt_info[device].rx_gpd;
+                tty_mgmt_info[device].rx_gpd = NULL;
+                tty_mgmt_info[device].rx_buf_offset = 0;
+                tty_mgmt_info[device].rx_gpd_num_assigned--;
+                TTY_SPIN_UNLOCK(tty_mgmt_info[device].spinLock);
+                QBM_FREE_ONE(rx_gpd);
+            } else {
+                TTY_SPIN_UNLOCK(tty_mgmt_info[device].spinLock);
+            }
+            
+        } else {
+            //change end for ALPS04065656
+            /* Inform upper layer module readyToRead */
+            if (tty_mgmt_info[device].conv_rx_cb) {
+                tty_mgmt_info[device].conv_rx_cb(device);
+            } else {
+                _tty_send_ilm(device, source_id, MSG_ID_UART_READY_TO_READ_IND);
+            }
+        }
+    } else
+    {   /* The rx callback is called by clear tx/rx buffer (flush) command */
+        QBM_FREE_ONE(rx_ior->first_gpd);
+        TTY_SPIN_LOCK(tty_mgmt_info[device].spinLock);
+        ASSERT(tty_mgmt_info[device].rx_gpd_num_assigned >= 1);
+        tty_mgmt_info[device].rx_gpd_num_assigned --;
+        if (tty_mgmt_info[device].rx_gpd_num_assigned == 0) {
+            /* clear flush_rx flag if all rx_gpd are free */
+            tty_mgmt_info[device].flush_rx = 0;
+        }
+        TTY_SPIN_UNLOCK(tty_mgmt_info[device].spinLock);
+    }
+
+    return STATUS_OK;
+}
+
+/*
+    _tty_rx_buff_cb is used for backward-compatible buffer mode driver.
+    This callback is only used for conventional user on buffer mode port.
+    The main task of this callback is sending ILM to tty user.
+    (Flush RX shall not go there.)
+*/
+DCL_STATUS DEVDRV_LS_DRAM_EX_ROCODE
+_tty_rx_buff_cb(
+    DCL_HANDLE          handle,
+    module_type         source_id,
+    tty_io_request_t    *rx_ior)
+{
+    DCL_DEV device;
+
+    device = DCL_UART_GET_DEV(handle);
+
+    /*Current design does not return data through callback*/
+    ASSERT(rx_ior == NULL);
+
+    TTY_SPIN_LOCK(tty_mgmt_info[device].spinLock);
+    if (tty_mgmt_info[device].rx_up_mod_wait)
+    { 
+        tty_mgmt_info[device].rx_up_mod_wait = 0;
+        TTY_SPIN_UNLOCK(tty_mgmt_info[device].spinLock);
+        if (tty_mgmt_info[device].conv_rx_cb) {
+            tty_mgmt_info[device].conv_rx_cb(device);
+        } else {
+            _tty_send_ilm(device, source_id, MSG_ID_UART_READY_TO_READ_IND);
+        }
+    }
+    else
+    {
+        TTY_SPIN_UNLOCK(tty_mgmt_info[device].spinLock);
+    }
+    return STATUS_OK;
+}
+
+
+DCL_STATUS DEVDRV_LS_DRAM_EX_ROCODE
+_tty_tx_done_cb(
+    DCL_HANDLE          handle,
+    module_type         source_id,
+    tty_io_request_t    *tx_ior)
+{
+    DCL_DEV device;
+    DCL_UINT32 number;
+
+    device = DCL_UART_GET_DEV(handle);
+
+    if (tx_ior) {
+        number = _tty_free_ior(tx_ior);
+
+        TTY_SPIN_LOCK(tty_mgmt_info[device].spinLock);
+        ASSERT(tty_mgmt_info[device].tx_gpd_num_used >= number);
+        tty_mgmt_info[device].tx_gpd_num_used -= number;
+        TTY_SPIN_UNLOCK(tty_mgmt_info[device].spinLock);
+
+        if (!tty_mgmt_info[device].flush_tx)
+        {
+            TTY_SPIN_LOCK(tty_mgmt_info[device].spinLock);
+            if (tty_mgmt_info[device].tx_up_mod_wait)
+            {
+                tty_mgmt_info[device].tx_up_mod_wait = 0;
+                TTY_SPIN_UNLOCK(tty_mgmt_info[device].spinLock);
+                if (tty_mgmt_info[device].conv_tx_cb) {
+                    tty_mgmt_info[device].conv_tx_cb(device);
+                } else {
+                    _tty_send_ilm(device, source_id, MSG_ID_UART_READY_TO_WRITE_IND);
+                }
+            }
+            else
+            {
+                TTY_SPIN_UNLOCK(tty_mgmt_info[device].spinLock);
+            }
+
+        } else {
+            TTY_SPIN_LOCK(tty_mgmt_info[device].spinLock);
+            if (tty_mgmt_info[device].tx_gpd_num_used == 0) {
+                /* clear flush_tx flag if all tx_gpd are free */
+                tty_mgmt_info[device].flush_tx = 0;
+            }
+            TTY_SPIN_UNLOCK(tty_mgmt_info[device].spinLock);
+        }
+    } else {
+        /* print error log - tx_ior can't be null */
+        if(INT_QueryExceptionStatus() == KAL_FALSE)
+MD_TRC(TTY_TR_TX_IOR_IS_NULL,device, source_id);
+        ASSERT(tx_ior);
+        return STATUS_FAIL;
+    }
+
+    return STATUS_OK;
+}
+
+/*
+    _tty_tx_buff_done_cb is used for backward-compatible buffer mode driver.
+    This callback is only used for conventional user on buffer mode port.
+    The main task of this callback is sending ILM to tty user.
+    (Flush TX shall not go there.)
+*/
+DCL_STATUS DEVDRV_LS_DRAM_EX_ROCODE
+_tty_tx_buff_done_cb(
+    DCL_HANDLE          handle,
+    module_type         source_id,
+    tty_io_request_t    *tx_ior)
+{
+    DCL_DEV device;
+
+    device = DCL_UART_GET_DEV(handle);
+
+    /*Current design does not return data through callback*/
+    ASSERT(tx_ior == NULL);
+
+     /* 
+     * This function is invoked when lower driver finish the TX.
+     * check up_mod_wait to send the indication message
+     */
+    TTY_SPIN_LOCK(tty_mgmt_info[device].spinLock);
+    if (tty_mgmt_info[device].tx_up_mod_wait)
+    { 
+        tty_mgmt_info[device].tx_up_mod_wait = 0;
+        TTY_SPIN_UNLOCK(tty_mgmt_info[device].spinLock);
+        if (tty_mgmt_info[device].conv_tx_cb) {
+            tty_mgmt_info[device].conv_tx_cb(device);
+        } else {
+            _tty_send_ilm(device, source_id, MSG_ID_UART_READY_TO_WRITE_IND);
+        }
+    }
+    else
+    {
+        TTY_SPIN_UNLOCK(tty_mgmt_info[device].spinLock);
+    }
+
+    return STATUS_OK;
+}
+
+void DEVDRV_LS_DRAM_EX_ROCODE
+_cal_and_set_rx_allow_len(
+    DCL_DEV      device,
+    DCL_UINT16   chunk_size)
+{
+    DCL_HANDLE handle;
+    UART_CTRL_GET_MTU_SIZE_T ur_ctrl_get_mtu_size;
+    
+    handle = DclSerialPort_Open(device, 0);
+    
+    if(chunk_size == 1)   //no chunk size restriction
+    {
+        DclSerialPort_Control(handle, TTY_CMD_GET_MTU_SIZE, (DCL_CTRL_DATA_T*)&ur_ctrl_get_mtu_size);
+        tty_mgmt_info[device].rx_allow_len = TTY_MIN(ur_ctrl_get_mtu_size.ulmtu_sz, tty_mgmt_info[device].qbm_data_len);
+    }
+    else
+    {
+        tty_mgmt_info[device].rx_allow_len = chunk_size;
+    }
+
+    ASSERT(tty_mgmt_info[device].rx_allow_len >= chunk_size);
+
+    if(INT_QueryExceptionStatus() == KAL_FALSE) 
+MD_TRC(TTY_TR_DRV_RX_ALLOW_LEN,device, tty_mgmt_info[device].rx_allow_len);
+    return;
+}
+
+
+DCL_STATUS DEVDRV_LS_DRAM_EX_ROCODE
+_tty_conv_assign_rx_gpd_to_drv(
+    DCL_DEV             device)
+{
+    DCL_STATUS result;
+    UART_CTRL_ASSIGN_RX_IOR_T ur_ctrl_assign_rxior;
+    tty_io_request_t *rx_ior;
+    void *rx_gpd_first, *rx_gpd_last;
+    DCL_UINT32 remain_rx_gpd_num;
+    DCL_UINT32 alloc_num;
+    SeriPort_HANLDER_CB sp_handler_cb;
+
+    TTY_SPIN_LOCK(tty_mgmt_info[device].spinLock);
+    if (!tty_mgmt_info[device].flush_rx && tty_mgmt_info[device].rx_gpd_num_assigned < 2 /*one for tailed gpd, another for real data receiving*/)
+    {
+        remain_rx_gpd_num = 2 - tty_mgmt_info[device].rx_gpd_num_assigned;
+        /** Add assigned gpd first to avoid conventional assign_rx_ior race condition , one is triggered in DclSerialPort_DrvAttach, the other is SIO_CMD_OPEN post-command*/
+        tty_mgmt_info[device].rx_gpd_num_assigned += remain_rx_gpd_num;
+        TTY_SPIN_UNLOCK(tty_mgmt_info[device].spinLock);
+
+        //alloc_num = qbmt_alloc_q_no_tail(TTY_QBM_DATA_TYPE, remain_rx_gpd_num, &rx_gpd_first, &rx_gpd_last);
+        alloc_num = qbmt_alloc_q_no_tail(tty_mgmt_info[device].qbm_data_type, remain_rx_gpd_num, &rx_gpd_first, &rx_gpd_last);
+        if (alloc_num != remain_rx_gpd_num)
+        {
+            TTY_SPIN_LOCK(tty_mgmt_info[device].spinLock);
+            /** Minus assigned gpd when cannot get gpds */
+            tty_mgmt_info[device].rx_gpd_num_assigned -= remain_rx_gpd_num;
+            TTY_SPIN_UNLOCK(tty_mgmt_info[device].spinLock);
+            if(INT_QueryExceptionStatus() == KAL_FALSE)
+MD_TRC(TTY_TR_GPD_EXHAUST,device, kal_get_active_module_id());
+            VAR_MSG_ASSERT(tty_internal_qbm_exhaust);
+            return STATUS_FAIL;
+        }
+        
+        //ASSERT(TTY_QBM_DATA_LEN >= tty_mgmt_info[device].chunk_size);
+        ASSERT(tty_mgmt_info[device].qbm_data_len >= tty_mgmt_info[device].chunk_size);
+
+        /* First gpd */
+        QBM_DES_SET_HWO(rx_gpd_first);
+        QBM_DES_SET_ALLOW_LEN(rx_gpd_first, tty_mgmt_info[device].rx_allow_len);
+        qbm_cal_set_checksum(rx_gpd_first);
+        QBM_CACHE_FLUSH(rx_gpd_first, sizeof(qbm_gpd));
+
+        /* Last gpd */
+        if (alloc_num == 2) {
+            QBM_DES_SET_HWO(rx_gpd_last);
+            QBM_DES_SET_ALLOW_LEN(rx_gpd_last, tty_mgmt_info[device].rx_allow_len);
+            qbm_cal_set_checksum(rx_gpd_last);
+            QBM_CACHE_FLUSH(rx_gpd_last, sizeof(qbm_gpd));
+        }
+        
+        rx_ior = (tty_io_request_t*)QBM_DES_GET_SW_CTRL_FIELD(rx_gpd_first);
+        rx_ior->first_gpd = rx_gpd_first;
+        rx_ior->last_gpd = rx_gpd_last;
+        rx_ior->next_request = NULL;
+
+        ur_ctrl_assign_rxior.u4OwnerId = tty_mgmt_info[device].owner_id;
+        ur_ctrl_assign_rxior.ior = rx_ior;
+        TTY_SPIN_LOCK(tty_mgmt_info[device].spinLock);
+        if (!tty_mgmt_info[device].sp_handler_cb) {
+            if(INT_QueryExceptionStatus() == KAL_FALSE)
+            MD_TRC(TTY_TR_DRV_CB_IS_NULL,device, kal_get_active_module_id());
+            TTY_SPIN_UNLOCK(tty_mgmt_info[device].spinLock);
+            _tty_free_ior(rx_ior);
+            return STATUS_FAIL;
+        }
+        sp_handler_cb = tty_mgmt_info[device].sp_handler_cb;
+        TTY_SPIN_UNLOCK(tty_mgmt_info[device].spinLock);
+        result = sp_handler_cb(device, TTY_CMD_ASSIGN_RX_IOR, (DCL_CTRL_DATA_T *)&ur_ctrl_assign_rxior);
+        if (result != STATUS_OK) {
+            /* command failed */
+            TTY_SPIN_LOCK(tty_mgmt_info[device].spinLock);
+            /** Minus assigned gpd when driver return fail */
+            tty_mgmt_info[device].rx_gpd_num_assigned -= remain_rx_gpd_num;
+            TTY_SPIN_UNLOCK(tty_mgmt_info[device].spinLock);
+            _tty_free_ior(rx_ior);
+            if(INT_QueryExceptionStatus() == KAL_FALSE)
+MD_TRC(TTY_TR_CMD_ERR_ASSIGN_RX_IOR,device, result, kal_get_active_module_id());
+            return result;
+        }
+    } else {
+        TTY_SPIN_UNLOCK(tty_mgmt_info[device].spinLock);
+    }
+
+    return STATUS_OK;
+}
+
+DCL_STATUS DEVDRV_LS_DRAM_EX_ROCODE
+_tty_conv_drv_state_change_cb(
+    DCL_HANDLE handle, 
+    tty_drv_state_e state)
+{
+    DCL_DEV device;
+
+    device = DCL_UART_GET_DEV(handle);
+
+    switch(state)
+    {
+        case DRV_ST_DETACHED: 
+        {
+            _tty_send_ilm(device, MOD_TTY, MSG_ID_UART_PLUGOUT_IND);
+            break;
+        }
+        case DRV_ST_ATTACHED:
+        {
+            _tty_send_ilm(device, MOD_TTY, MSG_ID_UART_PLUGIN_IND);
+            break;
+        }
+        default:
+        {
+            ASSERT(0);
+            break;
+        }
+    }
+
+    return STATUS_OK;
+}
+
+
+/* External used API */
+/* ==================================================================================================== */
+
+DCL_STATUS DEVDRV_LS_DRAM_EX_ROCODE
+DclSerialPort_Initialize(void)
+{
+#if !defined(TTY_HWITC_ENABLE)
+    kal_uint32 i;
+    kal_char tty_lock_name[50];
+#endif    
+    /* QBM number for TTY internal used must be larger than or equal to max possible gpd number for rx data path use */
+    /* we dont need to reserve GPD buffer for virtual port, because the driver mode of virtual port is buffer mode*/
+    //ASSERT(QBM_NUM_TTY_INT >= ((UART_DEV_CNT-CMUX_VP_NUM)*2/*2 buffer for Rx*/+(UART_DEV_CNT-CMUX_VP_NUM)*TTY_BC_TX_GPD_MAX_NUM/*Tx*/));
+    ASSERT(QBM_NUM_TTY_INT >= ((UART_DEV_CNT-CMUX_VP_NUM-CCCI_TTY_DEV_NUM)*2/*2 buffer for Rx*/));
+#if defined(__HIF_CCCI_SUPPORT__)
+    ASSERT(QBM_NUM_CCCI_COMM >= (CCCI_TTY_DEV_NUM*2/*2 buffer for Rx*/));
+#endif
+    
+    /*Init tty_mgmt_info instance*/
+    kal_mem_set(tty_mgmt_info, 0, sizeof(tty_port_mgmt)*UART_DEV_CNT);
+
+    /* Init lock resource */
+#if !defined(TTY_HWITC_ENABLE) 
+    /* HW ITC don't need create process, but spinlock needs */
+    for(i = 0; i < UART_DEV_CNT; i++)
+    {
+        sprintf(tty_lock_name, "TTYSPINLOCK_%d", i);
+        tty_mgmt_info[i].spinLock = kal_create_spinlock(tty_lock_name);
+        if(tty_mgmt_info[i].spinLock == NULL) ASSERT(0);
+    }
+#endif    
+    return STATUS_OK;
+}
+
+DCL_HANDLE DEVDRV_LS_DRAM_EX_ROCODE
+DclSerialPort_Open(
+    DCL_DEV             dev,
+    DCL_FLAGS           flags)
+{
+    
+    if ((dev<uart_port1) ||(dev>uart_max_port)) {
+        if(INT_QueryExceptionStatus() == KAL_FALSE)
+MD_TRC(TTY_TR_OPEN_ERR,dev, kal_get_active_module_id());
+        return STATUS_INVALID_DEVICE;
+    }
+
+    if (uart_port_null == dev) {
+        if(INT_QueryExceptionStatus() == KAL_FALSE)
+MD_TRC(TTY_TR_OPEN_ERR,dev, kal_get_active_module_id());
+        return STATUS_INVALID_DEVICE;
+    }
+
+    return (DCL_UART_MAGIC_NUM | dev);
+}
+
+DCL_STATUS DEVDRV_LS_DRAM_EX_ROCODE
+DclSerialPort_Close(
+    DCL_HANDLE          handle)
+{
+    return STATUS_OK;
+}
+
+DCL_STATUS DEVDRV_LS_DRAM_EX_ROCODE
+DclSerialPort_Configure(
+    DCL_HANDLE          handle,
+    DCL_CONFIGURE_T     *configure)
+{
+    return STATUS_OK;
+}
+
+
+/*!
+ *  @brief  If upper layer module execute DclSerialPort_UpModuleInit
+ *              ---> New Module Init
+ *              ---> In DclSerialPort_UpModuleInit, it will help send SIO_CMD_OPEN command
+ *          If upper layer module execute DclSerialPort_Control with SIO_CMD_OPEN command without calling DclSerialPort_UpModuleInit
+ *              ---> Old module init (for backward compatible)
+ */
+DCL_STATUS DEVDRV_LS_DRAM_EX_ROCODE
+DclSerialPort_Control(
+    DCL_HANDLE          handle,
+    DCL_CTRL_CMD        cmd,
+    DCL_CTRL_DATA_T     *data)
+{ 
+    DCL_STATUS result;
+    DCL_DEV device;
+    SeriPort_HANLDER_CB sp_handler_cb;
+
+    TTY_CHECK_HANDLE(handle);   
+    device = DCL_UART_GET_DEV(handle);
+    
+
+    /*20130313:SIO_CMD_OPEN will not check device exist*/
+    if (cmd == SIO_CMD_OPEN)
+    {
+        TTY_CHECK_DEV_VALID(device);
+        
+        /*If driver has not register yet, store the request*/
+        if(!tty_mgmt_info[device].active)
+        {
+            UART_CTRL_OPEN_T *ur_ctrl_open = &(data->rUARTCtrlOPEN);
+            
+            TTY_SPIN_LOCK(tty_mgmt_info[device].spinLock);
+            if (tty_mgmt_info[device].early_open_req) {
+                    TTY_SPIN_UNLOCK(tty_mgmt_info[device].spinLock);
+                    if(INT_QueryExceptionStatus() == KAL_FALSE) 
+MD_TRC(TTY_TR_CMD_OPEN_ALREADY_OPENED,device, kal_get_active_module_id());
+                    return STATUS_ALREADY_OPENED;
+            }
+            tty_mgmt_info[device].early_open_req = 1;
+            tty_mgmt_info[device].pending_owner = (module_type) ur_ctrl_open->u4OwenrId;
+            TTY_SPIN_UNLOCK(tty_mgmt_info[device].spinLock);
+            return STATUS_OK;
+        }
+    }
+    else if(cmd == SIO_CMD_CLOSE)
+    {
+        TTY_CHECK_DEV_VALID(device);
+        /*If driver has not register yet, store the request*/
+        if(!tty_mgmt_info[device].active)
+        {       
+            TTY_SPIN_LOCK(tty_mgmt_info[device].spinLock);
+            if (tty_mgmt_info[device].early_open_req) {
+                tty_mgmt_info[device].early_open_req = 0;
+                tty_mgmt_info[device].pending_owner = MOD_NIL;
+                if (tty_mgmt_info[device].early_tx_done_cb_req) 
+                {
+                    tty_mgmt_info[device].early_tx_done_cb_req = 0;
+                }
+                //clean info set by UpmoduleInit
+                if(tty_mgmt_info[device].init_by_new_mod)
+                {
+                    tty_mgmt_info[device].init_by_new_mod = 0;
+                    tty_mgmt_info[device].owner_id = MOD_NIL;
+                    tty_mgmt_info[device].flag = 0;
+                }
+                TTY_SPIN_UNLOCK(tty_mgmt_info[device].spinLock);
+            }
+            else
+            {
+                TTY_SPIN_UNLOCK(tty_mgmt_info[device].spinLock);
+                if(INT_QueryExceptionStatus() == KAL_FALSE) 
+MD_TRC(TTY_TR_DEV_IS_NOT_OPENED,device, kal_get_active_module_id());
+                return STATUS_NOT_OPENED;
+            }
+            
+            return STATUS_OK;
+        }
+    }
+    else
+    {
+        TTY_CHECK_DEV_IS_READY(device);
+    }
+#if TTY_AGGRESSIVE_TRACE
+    if(INT_QueryExceptionStatus() == KAL_FALSE)
+MD_TRC(TTY_TR_CMD_DCL_CONTROL,device, cmd, kal_get_active_module_id());
+#endif
+
+    /* Pre-command Process */
+    switch (cmd)
+    {
+        case SIO_CMD_OPEN:
+            {
+                TTY_SPIN_LOCK(tty_mgmt_info[device].spinLock);
+                if (tty_mgmt_info[device].opened) {
+                    TTY_SPIN_UNLOCK(tty_mgmt_info[device].spinLock);
+                    if(INT_QueryExceptionStatus() == KAL_FALSE) 
+MD_TRC(TTY_TR_CMD_OPEN_ALREADY_OPENED,device, kal_get_active_module_id());
+                    return STATUS_ALREADY_OPENED;
+                }
+                tty_mgmt_info[device].opened = 1;
+                TTY_SPIN_UNLOCK(tty_mgmt_info[device].spinLock);
+            }
+            break;
+
+        case SIO_CMD_GET_BYTES:
+        case SIO_CMD_GET_UART_BYTE:
+            {
+                UART_CTRL_GET_BYTES_T ur_ctrl_getbytes;
+                UART_CTRL_GET_BYTES_T *p_ur_ctrl_getbytes;
+                DCL_UINT16 real_data_len;
+                DCL_UINT8 *real_data;
+                void *rx_gpd;
+
+                if (!TTY_IS_CONVENTIONAL_RX(device)) {
+                    return STATUS_INVALID_OPERATION;
+                }
+
+                /* If device is buffer port, bypass cmd to driver*/
+                if(TTY_IS_BUFF_PORT(device))
+                {
+                    // TODO:add support for SIO_CMD_GET_UART_BYTE, which is blocking read. 
+                    ASSERT(cmd == SIO_CMD_GET_BYTES);
+                    break;
+                }
+                
+                /*
+                    This area is for conventional RX - backward compatible
+                */
+                if (cmd == SIO_CMD_GET_UART_BYTE) {
+                    UART_CTRL_GET_UART_BYTE_T *p_ur_ctrl_get_uart_byte;
+                    p_ur_ctrl_get_uart_byte = &(data->rUARTCtrlGETUARTBYTE);
+                    ur_ctrl_getbytes.puBuffaddr = &p_ur_ctrl_get_uart_byte->uByte;
+                    ur_ctrl_getbytes.u2Length = 1;
+                    p_ur_ctrl_getbytes = &ur_ctrl_getbytes;
+                } else {
+                    p_ur_ctrl_getbytes = &(data->rUARTCtrlGETBYTES);
+                }
+
+                if (TTY_DRV_IS_ATTACHED(device) && !   tty_mgmt_info[device].flush_rx) {
+                    _tty_conv_assign_rx_gpd_to_drv(device);
+                } else {
+                    p_ur_ctrl_getbytes->u2RetSize = 0;                  
+                    if(INT_QueryExceptionStatus() == KAL_FALSE) 
+MD_TRC(TTY_TR_WRONG_STATE,device, kal_get_active_module_id());
+                    return STATUS_ERROR_WRONG_STATE;
+                }
+
+                rx_gpd = tty_mgmt_info[device].rx_gpd;
+                if (!rx_gpd) {
+                    p_ur_ctrl_getbytes->u2RetSize = 0;
+#if TTY_AGGRESSIVE_TRACE                    
+                    if(INT_QueryExceptionStatus() == KAL_FALSE) 
+MD_TRC(TTY_TR_CMD_CONV_RX_NOT_RDY,device, kal_get_active_module_id());
+#endif
+                } else {
+                    real_data = (DCL_UINT8*)TTY_QBM_DES_GET_DATAPTR(rx_gpd) + tty_mgmt_info[device].rx_buf_offset;
+                    real_data_len = TTY_QBM_DES_GET_DATALEN(rx_gpd) - tty_mgmt_info[device].rx_buf_offset;
+
+                    if (real_data_len > p_ur_ctrl_getbytes->u2Length) {
+                        kal_mem_cpy(p_ur_ctrl_getbytes->puBuffaddr, real_data, p_ur_ctrl_getbytes->u2Length);
+                        p_ur_ctrl_getbytes->u2RetSize = p_ur_ctrl_getbytes->u2Length;
+                        tty_mgmt_info[device].rx_buf_offset += p_ur_ctrl_getbytes->u2Length;
+                    } else {
+                        kal_mem_cpy(p_ur_ctrl_getbytes->puBuffaddr, real_data, real_data_len);
+                        p_ur_ctrl_getbytes->u2RetSize = real_data_len;
+
+                        tty_mgmt_info[device].rx_buf_offset = 0;
+                        TTY_SPIN_LOCK(tty_mgmt_info[device].spinLock);
+                        tty_mgmt_info[device].rx_gpd = NULL;
+                        ASSERT(tty_mgmt_info[device].rx_gpd_num_assigned >= 1);
+                        tty_mgmt_info[device].rx_gpd_num_assigned --;
+                        TTY_SPIN_UNLOCK(tty_mgmt_info[device].spinLock);
+                        QBM_FREE_ONE(rx_gpd);
+
+                        /* Re-aasign rx gpd to driver for data receiveing */
+                        _tty_conv_assign_rx_gpd_to_drv(device);
+                    }
+                }
+#if TTY_AGGRESSIVE_TRACE                        
+                if(INT_QueryExceptionStatus() == KAL_FALSE) 
+MD_TRC(TTY_TR_CMD_CONV_RX,device, p_ur_ctrl_getbytes->u2RetSize);
+#endif
+                return STATUS_OK;
+            }
+            break;
+
+        case SIO_CMD_PUT_UART_BYTE:
+        case SIO_CMD_PUT_UART_BYTES:
+        case SIO_CMD_PUT_BYTES:
+        case SIO_CMD_PUT_ISR_BYTES:
+            {
+                UART_CTRL_PUT_BYTES_T ur_ctrl_putbytes;
+                UART_CTRL_PUT_BYTES_T *p_ur_ctrl_putbytes;
+                DCL_UINT8 *buf_ptr;
+                void *tx_gpd;
+                hif_io_request_t *tx_ior;
+                UART_CTRL_PUT_BYTES_IOR_T ur_ctrl_putbytes_ior;
+
+                if (!TTY_IS_CONVENTIONAL_TX(device)) {
+                    return STATUS_INVALID_OPERATION;
+                }
+
+                /* If device is buffer port, bypass cmd to driver*/
+                if(TTY_IS_BUFF_PORT(device))
+                {
+                    // TODO:add support for SIO_CMD_PUT_UART_BYTE(S), which are blocking write. 
+                    ASSERT(cmd == SIO_CMD_PUT_BYTES);
+                    break;
+                }
+                
+                /*
+                    This area is for conventional TX
+                */
+                if (cmd == SIO_CMD_PUT_UART_BYTE) {
+                    UART_CTRL_PUT_UART_BYTE_T *p_ur_ctrl_put_uart_byte;
+                    p_ur_ctrl_put_uart_byte = &(data->rUARTCtrlPUTUARTBYTE);
+                    ur_ctrl_putbytes.puBuffaddr = &p_ur_ctrl_put_uart_byte->uData;
+                    ur_ctrl_putbytes.u2Length = 1;
+                    p_ur_ctrl_putbytes = &ur_ctrl_putbytes;
+                } else if (cmd == SIO_CMD_PUT_UART_BYTES) {
+                    UART_CTRL_PUT_UART_BYTES_T *p_ur_ctrl_put_uart_bytes;
+                    p_ur_ctrl_put_uart_bytes = &(data->rUARTCtrlPUTUARTBYTES);
+                    ur_ctrl_putbytes.puBuffaddr = p_ur_ctrl_put_uart_bytes->puBuffaddr;
+                    ur_ctrl_putbytes.u2Length = p_ur_ctrl_put_uart_bytes->u2Length;
+                    p_ur_ctrl_putbytes = &ur_ctrl_putbytes;
+                } else {
+                    p_ur_ctrl_putbytes = &(data->rUARTCtrlPUTBYTES);
+                }
+
+                ASSERT(p_ur_ctrl_putbytes->u2Length);
+
+                if (!TTY_DRV_IS_ATTACHED(device) || tty_mgmt_info[device].flush_tx) {
+                    p_ur_ctrl_putbytes->u2RetSize = 0;                   
+                    if(INT_QueryExceptionStatus() == KAL_FALSE) 
+MD_TRC(TTY_TR_WRONG_STATE,device, kal_get_active_module_id());
+                    TTY_SPIN_LOCK(tty_mgmt_info[device].spinLock);
+                    tty_mgmt_info[device].tx_not_rdy = 1;
+                    TTY_SPIN_UNLOCK(tty_mgmt_info[device].spinLock);
+                    return STATUS_ERROR_WRONG_STATE;
+                }
+
+                TTY_SPIN_LOCK(tty_mgmt_info[device].spinLock);
+                if(!TTY_CHK_DEV_OPEN(device)){
+                    p_ur_ctrl_putbytes->u2RetSize = 0;
+                    TTY_SPIN_UNLOCK(tty_mgmt_info[device].spinLock);
+                    return STATUS_NOT_OPENED;
+                }
+                TTY_SPIN_UNLOCK(tty_mgmt_info[device].spinLock);
+
+                TTY_SPIN_LOCK(tty_mgmt_info[device].spinLock);
+                if (tty_mgmt_info[device].tx_gpd_num_used >= TTY_BC_TX_GPD_MAX_NUM) {
+                    /* tx ior is not yet retrieved, still in driver */
+                    p_ur_ctrl_putbytes->u2RetSize = 0;
+                    if (cmd != SIO_CMD_PUT_ISR_BYTES) {
+                        tty_mgmt_info[device].tx_up_mod_wait = 1;
+                    }
+                    TTY_SPIN_UNLOCK(tty_mgmt_info[device].spinLock);
+#if TTY_AGGRESSIVE_TRACE
+                    if(INT_QueryExceptionStatus() == KAL_FALSE) 
+MD_TRC(TTY_TR_CMD_CONV_TX_NOT_RDY,device, tty_mgmt_info[device].tx_gpd_num_used, kal_get_active_module_id());
+#endif
+                } else {
+                    TTY_SPIN_UNLOCK(tty_mgmt_info[device].spinLock);
+                    //tx_gpd = QBM_ALLOC_ONE(TTY_QBM_DATA_TYPE);
+                    tx_gpd = QBM_ALLOC_ONE(tty_mgmt_info[device].qbm_data_type);
+
+                    if (tx_gpd)
+                    {
+                        TTY_SPIN_LOCK(tty_mgmt_info[device].spinLock);
+                        tty_mgmt_info[device].tx_gpd_num_used ++;
+                        TTY_SPIN_UNLOCK(tty_mgmt_info[device].spinLock);
+                        
+                        tx_ior = (hif_io_request_t*)QBM_DES_GET_SW_CTRL_FIELD(tx_gpd);
+                        tx_ior->next_request = NULL;
+                        tx_ior->first_gpd = tx_gpd;
+                        tx_ior->last_gpd = tx_gpd;
+
+                        ur_ctrl_putbytes_ior.u4OwnerId = tty_mgmt_info[device].owner_id;
+                        ur_ctrl_putbytes_ior.putIor = (void*)tx_ior;
+                        
+                        buf_ptr = TTY_QBM_DES_GET_DATAPTR(tx_gpd);
+
+                        //if (TTY_QBM_DATA_LEN >= p_ur_ctrl_putbytes->u2Length) {
+                        if (tty_mgmt_info[device].qbm_data_len >= p_ur_ctrl_putbytes->u2Length) {
+                            kal_mem_cpy(buf_ptr, p_ur_ctrl_putbytes->puBuffaddr, p_ur_ctrl_putbytes->u2Length);
+                            p_ur_ctrl_putbytes->u2RetSize = p_ur_ctrl_putbytes->u2Length;
+                            if (cmd != SIO_CMD_PUT_ISR_BYTES) {
+                                TTY_SPIN_LOCK(tty_mgmt_info[device].spinLock);
+                                tty_mgmt_info[device].tx_up_mod_wait = 0;
+                                TTY_SPIN_UNLOCK(tty_mgmt_info[device].spinLock);
+                            }
+                        } else {
+                            //kal_mem_cpy(buf_ptr, p_ur_ctrl_putbytes->puBuffaddr, TTY_QBM_DATA_LEN);
+                            //p_ur_ctrl_putbytes->u2RetSize = TTY_QBM_DATA_LEN;
+                            kal_mem_cpy(buf_ptr, p_ur_ctrl_putbytes->puBuffaddr, tty_mgmt_info[device].qbm_data_len);
+                            p_ur_ctrl_putbytes->u2RetSize = tty_mgmt_info[device].qbm_data_len;
+                            if (cmd != SIO_CMD_PUT_ISR_BYTES) {
+                                TTY_SPIN_LOCK(tty_mgmt_info[device].spinLock);
+                                tty_mgmt_info[device].tx_up_mod_wait = 1;
+                                TTY_SPIN_UNLOCK(tty_mgmt_info[device].spinLock);
+                            }
+                        }
+
+                        TTY_QBM_DES_SET_DATALEN(tx_gpd, p_ur_ctrl_putbytes->u2RetSize); // Set data length
+
+                        //QBM_CACHE_FLUSH(buf_ptr, p_ur_ctrl_putbytes->u2RetSize);   // khr debug, flush data
+#if TTY_AGGRESSIVE_TRACE                        
+                        if(INT_QueryExceptionStatus() == KAL_FALSE) 
+MD_TRC(TTY_TR_CMD_CONV_TX,device, p_ur_ctrl_putbytes->u2RetSize);
+#endif
+                        TTY_SPIN_LOCK(tty_mgmt_info[device].spinLock);
+                        if (!tty_mgmt_info[device].sp_handler_cb) {
+                            if(INT_QueryExceptionStatus() == KAL_FALSE)
+                            MD_TRC(TTY_TR_DRV_CB_IS_NULL,device, kal_get_active_module_id());
+                            tty_mgmt_info[device].tx_gpd_num_used --;
+                            if (cmd != SIO_CMD_PUT_ISR_BYTES) {
+                                tty_mgmt_info[device].tx_up_mod_wait = 1;
+                            }
+                            TTY_SPIN_UNLOCK(tty_mgmt_info[device].spinLock);
+                            QBM_FREE_ONE(tx_gpd);
+                            p_ur_ctrl_putbytes->u2RetSize = 0;
+                            return STATUS_FAIL;
+                        }
+                        sp_handler_cb = tty_mgmt_info[device].sp_handler_cb;
+                        TTY_SPIN_UNLOCK(tty_mgmt_info[device].spinLock);
+                        result = sp_handler_cb(device, TTY_CMD_PUT_BYTES_IOR, (DCL_CTRL_DATA_T *)&ur_ctrl_putbytes_ior);
+                        if (result != STATUS_OK) {
+                            /* command failed */
+                            QBM_FREE_ONE(tx_gpd);
+                            TTY_SPIN_LOCK(tty_mgmt_info[device].spinLock);
+                            tty_mgmt_info[device].tx_gpd_num_used --;
+                            if (cmd != SIO_CMD_PUT_ISR_BYTES) {
+                                tty_mgmt_info[device].tx_up_mod_wait = 1;
+                            }
+                            TTY_SPIN_UNLOCK(tty_mgmt_info[device].spinLock);
+                            p_ur_ctrl_putbytes->u2RetSize = 0;
+                            if(INT_QueryExceptionStatus() == KAL_FALSE)
+MD_TRC(TTY_TR_CMD_ERR_PUT_BYTES_IOR,device, result, kal_get_active_module_id());
+                            return result;
+                        }
+                    } else {
+                        if(INT_QueryExceptionStatus() == KAL_FALSE) 
+MD_TRC(TTY_TR_GPD_EXHAUST,device, kal_get_active_module_id());
+                        //This case has error handling, so remove assert check here.
+                        //VAR_MSG_ASSERT(tty_internal_gpd_exhaust);
+                        p_ur_ctrl_putbytes->u2RetSize = 0;
+                        if (cmd != SIO_CMD_PUT_ISR_BYTES) {
+                            TTY_SPIN_LOCK(tty_mgmt_info[device].spinLock);
+                            tty_mgmt_info[device].tx_up_mod_wait = 1;
+                            TTY_SPIN_UNLOCK(tty_mgmt_info[device].spinLock);
+                        }
+                    }
+                }
+
+                return STATUS_OK;
+            }
+            break;
+            
+        case SIO_CMD_GET_RX_AVAIL:
+            {           
+                UART_CTRL_RX_AVAIL_T *ur_ctrl_rx_avail;
+                ur_ctrl_rx_avail = &(data->rUARTCtrlRXAVAIL);
+
+                /* If device is buffer port, bypass cmd to driver*/
+                if(TTY_IS_BUFF_PORT(device) && TTY_IS_CONVENTIONAL_RX(device))
+                {
+                    break;
+                }
+                
+                if (TTY_IS_CONVENTIONAL_RX(device))
+                {
+                    if (tty_mgmt_info[device].rx_gpd) {
+                        ur_ctrl_rx_avail->u2RetSize = TTY_QBM_DES_GET_DATALEN(tty_mgmt_info[device].rx_gpd) - tty_mgmt_info[device].rx_buf_offset;
+                    } else {
+                        ur_ctrl_rx_avail->u2RetSize = 0;
+                    }
+                    return STATUS_OK;
+                } else
+                {
+                    return STATUS_FAIL; // This command doesn't be suported in NEW TTY Rx path
+                }
+            }
+            break;
+            
+        case SIO_CMD_GET_TX_AVAIL:
+        case SIO_CMD_GET_ISR_TX_AVAIL:
+            {
+                UART_CTRL_TX_AVAIL_T *ur_ctrl_tx_avail;
+                ur_ctrl_tx_avail = &(data->rUARTCtrlTXAVAIL);
+                
+                /* If device is buffer port, bypass cmd to driver*/
+                if(TTY_IS_BUFF_PORT(device) && TTY_IS_CONVENTIONAL_TX(device))
+                {
+                    break;
+                }
+
+                if (TTY_IS_CONVENTIONAL_TX(device))
+                {
+                    TTY_SPIN_LOCK(tty_mgmt_info[device].spinLock);
+                    if (tty_mgmt_info[device].tx_gpd_num_used >= TTY_BC_TX_GPD_MAX_NUM) {
+                        /* If Tx ior is in driver, return Tx available room = 0 byte */
+                        ur_ctrl_tx_avail->u2RetSize = 0;
+                    } else {
+                        /* If Tx ior is retrieved and available, return Tx available room = TTY_QBM_DATA_LEN byte */
+                        //ur_ctrl_tx_avail->u2RetSize = TTY_QBM_DATA_LEN;
+                        ur_ctrl_tx_avail->u2RetSize = tty_mgmt_info[device].qbm_data_len;
+                    }
+                    TTY_SPIN_UNLOCK(tty_mgmt_info[device].spinLock);
+
+                    return STATUS_OK;
+                } else
+                {
+                    return STATUS_FAIL; // This command doesn't be suported in NEW TTY Tx path
+                }
+            }
+            break;
+
+        case TTY_CMD_GET_DRV_STATE:
+            {
+                UART_CTRL_GET_DRV_STATE_T *ur_ctrl_get_drv_st;
+                ur_ctrl_get_drv_st = &(data->rUARTCtrlGetDrvState);
+
+                ur_ctrl_get_drv_st->drv_state = tty_mgmt_info[device].drv_state;
+
+                return STATUS_OK;
+            }
+            break;
+
+        case SIO_CMD_REG_TX_CB:
+            {
+                UART_CTRL_REG_TX_CB_T *ur_ctrl_reg_tx_cb;
+                ur_ctrl_reg_tx_cb = &(data->rUARTCtrlREGTXCB);
+
+                if (!TTY_IS_CONVENTIONAL_TX(device)) {
+                    return STATUS_INVALID_OPERATION;
+                }
+
+                tty_mgmt_info[device].conv_tx_cb = ur_ctrl_reg_tx_cb->func;
+                
+                return STATUS_OK;
+            }
+            break;
+            
+        case SIO_CMD_REG_RX_CB:
+            {
+                UART_CTRL_REG_RX_CB_T *ur_ctrl_reg_rx_cb;
+                ur_ctrl_reg_rx_cb = &(data->rUARTCtrlREGRXCB);
+
+                if (!TTY_IS_CONVENTIONAL_RX(device)) {
+                    return STATUS_INVALID_OPERATION;
+                }
+
+                tty_mgmt_info[device].conv_rx_cb = ur_ctrl_reg_rx_cb->func;
+
+                return STATUS_OK;
+            }
+            break;
+
+        case SIO_CMD_SET_OWNER:
+        case SIO_CMD_CLOSE:
+            {
+                /* Only GPD port will reference this flag*/
+                if(!TTY_IS_BUFF_PORT(device))
+                {
+                    tty_mgmt_info[device].flush_tx = 1;
+                    tty_mgmt_info[device].flush_rx = 1;
+
+                }
+                /* Check if there is any rx buff store in tty*/
+                if(TTY_IS_CONVENTIONAL_RX(device))
+                {
+                    void *rx_gpd;
+                    TTY_SPIN_LOCK(tty_mgmt_info[device].spinLock);
+                    if (tty_mgmt_info[device].rx_gpd) {
+                        rx_gpd = tty_mgmt_info[device].rx_gpd;
+                        tty_mgmt_info[device].rx_gpd = NULL;
+                        tty_mgmt_info[device].rx_buf_offset = 0;
+                        tty_mgmt_info[device].rx_gpd_num_assigned--;
+                        TTY_SPIN_UNLOCK(tty_mgmt_info[device].spinLock);
+                        QBM_FREE_ONE(rx_gpd);
+                    }
+                    else
+                    {
+                        TTY_SPIN_UNLOCK(tty_mgmt_info[device].spinLock);
+                    }
+                }
+            }
+            break;
+        case SIO_CMD_CLR_TX_BUF:
+            {
+                /* CCCI driver doesn't support TX flush command 
+                 * beacause some port share the same HW queue.
+                 */
+                if(DCL_UART_CCCI_TYPE != tty_mgmt_info[device].dev_type){
+                    /*Buffer port need to clear tx_up_mod_wait_flag*/
+                    if(TTY_IS_BUFF_PORT(device)){
+                        TTY_SPIN_LOCK(tty_mgmt_info[device].spinLock);
+                        tty_mgmt_info[device].tx_up_mod_wait = 1;
+                        TTY_SPIN_UNLOCK(tty_mgmt_info[device].spinLock);
+                    }
+                    else {
+                        /* Only GPD port will reference this flag*/
+                        tty_mgmt_info[device].flush_tx = 1;
+                    }
+                }
+            }
+            break;
+        case SIO_CMD_CLR_RX_BUF:
+            {
+                void *rx_gpd;
+                /* Only GPD port will reference this flag*/
+                if(!TTY_IS_BUFF_PORT(device))
+                {
+                    tty_mgmt_info[device].flush_rx = 1;
+                }
+                /* Check if there is any rx buff store in tty*/
+                if (TTY_IS_CONVENTIONAL_RX(device))
+                {
+                    TTY_SPIN_LOCK(tty_mgmt_info[device].spinLock);
+                    if (tty_mgmt_info[device].rx_gpd) {
+                        rx_gpd = tty_mgmt_info[device].rx_gpd;
+                        tty_mgmt_info[device].rx_gpd = NULL;
+                        tty_mgmt_info[device].rx_buf_offset = 0;
+                        tty_mgmt_info[device].rx_gpd_num_assigned--;
+                        TTY_SPIN_UNLOCK(tty_mgmt_info[device].spinLock);
+                        QBM_FREE_ONE(rx_gpd);
+                    }
+                    else
+                    {
+                        TTY_SPIN_UNLOCK(tty_mgmt_info[device].spinLock);
+                    }
+                }
+                /*Buffer port need to clear rx_up_mod_wait_flag*/
+                if(TTY_IS_BUFF_PORT(device))
+                {
+                    TTY_SPIN_LOCK(tty_mgmt_info[device].spinLock);
+                    tty_mgmt_info[device].rx_up_mod_wait = 1;
+                    TTY_SPIN_UNLOCK(tty_mgmt_info[device].spinLock);
+                }            
+            }
+            break;      
+        case SIO_CMD_SEND_ISR_DATA:
+        case SIO_CMD_SEND_DATA:
+            {
+                VAR_MSG_ASSERT(not_support_sio_command);
+            }
+            break;
+        case TTY_CMD_SET_INDICATION:
+            {
+                UART_CTRL_SET_INDICATION_T *ur_ctrl_set_indication;
+                ur_ctrl_set_indication = &(data->rUARTCtrlSETINDICATION);
+
+                if(ur_ctrl_set_indication->need_indication == 0)
+                {
+                    tty_mgmt_info[device].no_indication = 1;
+                }
+                
+            }
+            break;
+        default:
+            break;
+    }
+    TTY_SPIN_LOCK(tty_mgmt_info[device].spinLock);
+    if (!tty_mgmt_info[device].sp_handler_cb) {
+        if(INT_QueryExceptionStatus() == KAL_FALSE)
+        MD_TRC(TTY_TR_DRV_CB_IS_NULL,device, kal_get_active_module_id());
+        if (cmd == SIO_CMD_OPEN) {
+            tty_mgmt_info[device].opened = 0;
+        }
+        TTY_SPIN_UNLOCK(tty_mgmt_info[device].spinLock);
+        return STATUS_FAIL;
+    }
+    sp_handler_cb = tty_mgmt_info[device].sp_handler_cb;
+    TTY_SPIN_UNLOCK(tty_mgmt_info[device].spinLock);
+    result = sp_handler_cb(device, cmd, data);
+    
+    if (result != STATUS_OK) {
+        if (cmd == SIO_CMD_OPEN) {
+            /* open failed */
+            TTY_SPIN_LOCK(tty_mgmt_info[device].spinLock);
+            tty_mgmt_info[device].opened = 0;
+            TTY_SPIN_UNLOCK(tty_mgmt_info[device].spinLock);
+        }
+        if(INT_QueryExceptionStatus() == KAL_FALSE)
+MD_TRC(TTY_TR_DCL_CMD_NG,device, cmd, result);
+        return result;
+    }
+
+    /* Post-command Process */
+    switch (cmd)
+    {           
+        case SIO_CMD_OPEN:
+            {
+                if (!tty_mgmt_info[device].init_by_new_mod)
+                {   /* Conventional Module Init */
+                    UART_CTRL_OPEN_T *ur_ctrl_open;
+
+                    if(INT_QueryExceptionStatus() == KAL_FALSE) 
+MD_TRC(TTY_TR_CONV_INIT,device, kal_get_active_module_id());
+                    
+                    tty_mgmt_info[device].rx_gpd = NULL;
+                    TTY_SPIN_LOCK(tty_mgmt_info[device].spinLock);
+                    tty_mgmt_info[device].rx_gpd_num_assigned = 0;
+                    TTY_SPIN_UNLOCK(tty_mgmt_info[device].spinLock);
+                    tty_mgmt_info[device].rx_buf_offset = 0;
+                    tty_mgmt_info[device].flag = 0;
+                    tty_mgmt_info[device].no_indication = 0;
+                    
+                    ur_ctrl_open = &(data->rUARTCtrlOPEN);
+                    tty_mgmt_info[device].owner_id = (module_type)ur_ctrl_open->u4OwenrId;
+
+                    /* buffer port shall register different callback*/
+                    if(TTY_IS_BUFF_PORT(device))
+                    {
+                        _DclSerialPort_UpModuleRegisterCb(device, _tty_rx_buff_cb, _tty_tx_buff_done_cb, NULL);
+                    }
+                    else
+                    {
+                        /* 20130617: Add drv_state_change callback for supporting plug-in/plug-out indication*/
+                        _DclSerialPort_UpModuleRegisterCb(device, _tty_rx_cb, _tty_tx_done_cb, _tty_conv_drv_state_change_cb);
+                    }
+                }
+
+                /* Init rx_up_mod_wait for buffer port*/
+                if(TTY_IS_BUFF_PORT(device))
+                {
+                    TTY_SPIN_LOCK(tty_mgmt_info[device].spinLock);
+                    tty_mgmt_info[device].rx_up_mod_wait = 1;
+                    TTY_SPIN_UNLOCK(tty_mgmt_info[device].spinLock);
+                }
+                
+                /* If upper module firstly send SIO_CMD_OPEN command & use conventional Rx path, tty will help send TTY_CMD_ASSIGN_RX_IOR to assign RX IOR to driver */
+                /* Only takes when GPD ports*/
+                if(!TTY_IS_BUFF_PORT(device))
+                {
+                    if (TTY_IS_CONVENTIONAL_RX(device) && TTY_DRV_IS_ATTACHED(device))
+                    {
+                        _tty_conv_assign_rx_gpd_to_drv(device);
+                    }
+                }
+            }
+            break;
+        case SIO_CMD_SET_OWNER:
+            {
+                UART_CTRL_OWNER_T *ur_ctrl_owner;
+                DCL_UINT32 count;
+                
+                ur_ctrl_owner = &(data->rUARTCtrlOWNER);
+
+                /* Only GPD port needs to check if all GPDs of previous user are returned*/
+                if(!TTY_IS_BUFF_PORT(device))
+                {
+                    TTY_CONV_FLUSH_TX(10);
+                    TTY_CONV_FLUSH_RX(10);
+                }
+                
+                /* Reset parameters */
+                tty_mgmt_info[device].flag = 0;
+                tty_mgmt_info[device].rx_gpd = NULL;
+                tty_mgmt_info[device].rx_buf_offset = 0;
+                TTY_SPIN_LOCK(tty_mgmt_info[device].spinLock);
+                tty_mgmt_info[device].tx_up_mod_wait = 0;
+                TTY_SPIN_UNLOCK(tty_mgmt_info[device].spinLock);
+                tty_mgmt_info[device].conv_tx_cb = NULL;
+                tty_mgmt_info[device].conv_rx_cb = NULL;
+                tty_mgmt_info[device].flush_tx = 0;
+                tty_mgmt_info[device].flush_rx = 0;
+                tty_mgmt_info[device].owner_id = (module_type)ur_ctrl_owner->u4OwenrId;
+                tty_mgmt_info[device].no_indication= 0;
+
+                if(!TTY_IS_BUFF_PORT(device))
+                {
+                    /* Pre-assign Rx gpd if conventional Rx path is used */
+                    if (TTY_DRV_IS_ATTACHED(device) && TTY_IS_CONVENTIONAL_RX(device))
+                    {
+                        _tty_conv_assign_rx_gpd_to_drv(device);
+                    }
+
+                    /* By default set all callback functions with tty internal handler */
+                    _DclSerialPort_UpModuleRegisterCb(device, _tty_rx_cb, _tty_tx_done_cb, NULL);
+                }
+                else
+                {
+                    /* buffer port, just register buff port callback*/
+                    _DclSerialPort_UpModuleRegisterCb(device, _tty_rx_buff_cb, _tty_tx_buff_done_cb, NULL);
+                }
+            }
+            break;
+        case SIO_CMD_CLR_TX_BUF:
+            {
+                DCL_UINT32 count;
+
+                if(DCL_UART_CCCI_TYPE != tty_mgmt_info[device].dev_type){
+                    /* Only GPD port needs to check if all GPDs of previous user are returned*/
+                    if(!TTY_IS_BUFF_PORT(device)){
+                        TTY_CONV_FLUSH_TX(10);
+                        tty_mgmt_info[device].flush_tx = 0;
+                    }
+                }
+            }
+            break;
+        case SIO_CMD_CLR_RX_BUF:
+            {
+                DCL_UINT32 count;
+
+                /* Only GPD port needs to check if all GPDs of previous user are returned*/
+                if(!TTY_IS_BUFF_PORT(device))
+                {
+                    TTY_CONV_FLUSH_RX(10);
+
+                    tty_mgmt_info[device].flush_rx = 0;
+
+                    if (TTY_DRV_IS_ATTACHED(device) && TTY_IS_CONVENTIONAL_RX(device))
+                    {
+                        _tty_conv_assign_rx_gpd_to_drv(device);
+                    }
+                }
+            }
+            break;
+        case SIO_CMD_CLOSE:
+            {
+                DCL_UINT32 count;
+
+                /* Only GPD port needs to check if all GPDs of previous user are returned*/
+                if(!TTY_IS_BUFF_PORT(device))
+                {
+                    TTY_CONV_FLUSH_TX(10);
+                    TTY_CONV_FLUSH_RX(10);
+                }
+                
+                tty_mgmt_info[device].flush_tx = 0;
+                tty_mgmt_info[device].flush_rx = 0;
+                tty_mgmt_info[device].flag = 0;
+                tty_mgmt_info[device].init_by_new_mod = 0;
+                TTY_SPIN_LOCK(tty_mgmt_info[device].spinLock);
+                tty_mgmt_info[device].opened = 0;
+                tty_mgmt_info[device].rx_gpd_num_assigned = 0;
+                tty_mgmt_info[device].tx_gpd_num_used = 0;
+                TTY_SPIN_UNLOCK(tty_mgmt_info[device].spinLock);
+                tty_mgmt_info[device].rx_buf_offset = 0;
+                tty_mgmt_info[device].conv_tx_cb = NULL;
+                tty_mgmt_info[device].conv_rx_cb = NULL;
+                tty_mgmt_info[device].no_indication= 0;
+            }
+            break;
+        //case SIO_CMD_PUT_UART_BYTE:             //not support in buffer port currently
+        //case SIO_CMD_PUT_UART_BYTES:            //not support in buffer port currently
+        //case SIO_CMD_PUT_ISR_BYTES:             //not support in buffer port currently
+        case SIO_CMD_PUT_BYTES:    
+            {
+                UART_CTRL_PUT_BYTES_T *p_ur_ctrl_putbytes;
+                UART_CTRL_TX_AVAIL_T ur_ctrl_tx_avail;
+                
+                //GPD port shall not go here.
+                ASSERT(TTY_IS_BUFF_PORT(device));
+
+                /*
+                    Only SIO_CMD_PUT_BYTES will return length of transmitted data
+                */
+                if(cmd == SIO_CMD_PUT_BYTES)
+                {
+                    p_ur_ctrl_putbytes = &(data->rUARTCtrlPUTBYTES);
+                    if(p_ur_ctrl_putbytes->u2Length != p_ur_ctrl_putbytes->u2RetSize)
+                    {
+                        TTY_SPIN_LOCK(tty_mgmt_info[device].spinLock);
+                        tty_mgmt_info[device].tx_up_mod_wait = 1;
+
+                        /*
+                         Ready to write message may lost before setting tx_up_mod_wait as 1. 
+                         (Due to user task priority may be lower than HIF task priority)
+                         so we need to double confirmed with HIF driver if it is really no space to write
+                        */
+                        ur_ctrl_tx_avail.u2RetSize = 0;
+                        if (!tty_mgmt_info[device].sp_handler_cb) {
+                            if(INT_QueryExceptionStatus() == KAL_FALSE)
+                            MD_TRC(TTY_TR_DRV_CB_IS_NULL,device, kal_get_active_module_id());
+                            TTY_SPIN_UNLOCK(tty_mgmt_info[device].spinLock);  
+                            return STATUS_FAIL;
+                        }
+                        sp_handler_cb = tty_mgmt_info[device].sp_handler_cb;
+                        TTY_SPIN_UNLOCK(tty_mgmt_info[device].spinLock);
+                        sp_handler_cb(device, SIO_CMD_GET_TX_AVAIL, (DCL_CTRL_DATA_T *)&ur_ctrl_tx_avail);
+                        if(ur_ctrl_tx_avail.u2RetSize > 0)
+                        {
+                            TTY_SPIN_LOCK(tty_mgmt_info[device].spinLock);
+                            if( tty_mgmt_info[device].tx_up_mod_wait == 1)
+                            {
+                                tty_mgmt_info[device].tx_up_mod_wait = 0;
+                                TTY_SPIN_UNLOCK(tty_mgmt_info[device].spinLock);
+                                _tty_send_ilm(device, MOD_TTY, MSG_ID_UART_READY_TO_WRITE_IND);
+                            }
+                            else
+                            {
+                                TTY_SPIN_UNLOCK(tty_mgmt_info[device].spinLock);
+                            }
+                        }
+                    }
+                }
+            }
+            break;
+        case SIO_CMD_GET_BYTES:
+        //case SIO_CMD_GET_UART_BYTE:            //not support in buffer port currently
+            {
+                UART_CTRL_GET_BYTES_T *p_ur_ctrl_getbytes;
+                UART_CTRL_RX_AVAIL_T ur_ctrl_rx_avail;
+                
+                //GPD port shall not go here.
+                ASSERT(TTY_IS_BUFF_PORT(device));
+
+                if(cmd == SIO_CMD_GET_BYTES)
+                {
+                    p_ur_ctrl_getbytes = &(data->rUARTCtrlGETBYTES);
+                    //Last read
+                    if(p_ur_ctrl_getbytes->u2Length > p_ur_ctrl_getbytes->u2RetSize)
+                    {
+                        TTY_SPIN_LOCK(tty_mgmt_info[device].spinLock);
+                        tty_mgmt_info[device].rx_up_mod_wait = 1;
+
+
+                        /*
+                         Ready to read message may lost before setting rx_up_mod_wait as 1.
+                         (Due to user task priority may be lower than HIF task priority)
+                         so we need to double confirmed with HIF driver if it is really no data ready to read
+                        */
+                        ur_ctrl_rx_avail.u2RetSize = 0;
+                            if (!tty_mgmt_info[device].sp_handler_cb) {
+                                if(INT_QueryExceptionStatus() == KAL_FALSE)
+                                MD_TRC(TTY_TR_DRV_CB_IS_NULL,device, kal_get_active_module_id());
+                                TTY_SPIN_UNLOCK(tty_mgmt_info[device].spinLock);  
+                                return STATUS_FAIL;
+                            }
+                         
+                        sp_handler_cb = tty_mgmt_info[device].sp_handler_cb;                         
+                        TTY_SPIN_UNLOCK(tty_mgmt_info[device].spinLock);
+                        sp_handler_cb(device, SIO_CMD_GET_RX_AVAIL, (DCL_CTRL_DATA_T *)&ur_ctrl_rx_avail);
+                        if(ur_ctrl_rx_avail.u2RetSize > 0)
+                        {
+                            TTY_SPIN_LOCK(tty_mgmt_info[device].spinLock);
+                            if( tty_mgmt_info[device].rx_up_mod_wait == 1)
+                            {
+                                tty_mgmt_info[device].rx_up_mod_wait = 0;
+                                TTY_SPIN_UNLOCK(tty_mgmt_info[device].spinLock);
+                                _tty_send_ilm(device, MOD_TTY, MSG_ID_UART_READY_TO_READ_IND);
+                            }
+                            else
+                            {
+                                TTY_SPIN_UNLOCK(tty_mgmt_info[device].spinLock);
+                            }
+                        }
+                    }
+                }
+            }
+            break;
+        default:
+            break;
+    }
+
+    return result;  
+}
+
+DCL_STATUS DEVDRV_LS_DRAM_EX_ROCODE
+DclSerialPort_UpModuleInit(
+    DCL_HANDLE          handle,
+    module_type         module_id,
+    int                 flag)
+{
+    DCL_STATUS status = STATUS_FAIL;
+    DCL_DEV device;
+    UART_CTRL_OPEN_T uCtlOpen;
+
+    TTY_CHECK_HANDLE(handle);
+    device = DCL_UART_GET_DEV(handle);
+
+    /*20130313:remove driver active check, because user may do initial flow before driver in active state*/
+    TTY_CHECK_DEV_VALID(device);
+
+    if(INT_QueryExceptionStatus() == KAL_FALSE) 
+MD_TRC(TTY_TR_NEW_INIT,device,module_id);
+
+    TTY_SPIN_LOCK(tty_mgmt_info[device].spinLock);
+    if (tty_mgmt_info[device].opened || tty_mgmt_info[device].early_open_req) {
+        TTY_SPIN_UNLOCK(tty_mgmt_info[device].spinLock);
+        if(INT_QueryExceptionStatus() == KAL_FALSE) 
+MD_TRC(TTY_TR_CMD_OPEN_ALREADY_OPENED,device, module_id);
+        return STATUS_ALREADY_OPENED;
+    }
+    TTY_SPIN_UNLOCK(tty_mgmt_info[device].spinLock);
+    
+    tty_mgmt_info[device].owner_id = module_id;
+    tty_mgmt_info[device].flag = flag;
+    tty_mgmt_info[device].init_by_new_mod = 1;
+    tty_mgmt_info[device].rx_gpd = NULL;
+    tty_mgmt_info[device].rx_buf_offset = 0;
+    TTY_SPIN_LOCK(tty_mgmt_info[device].spinLock);
+    tty_mgmt_info[device].rx_gpd_num_assigned = 0;
+    tty_mgmt_info[device].tx_gpd_num_used = 0;
+    tty_mgmt_info[device].tx_up_mod_wait = 0;
+    TTY_SPIN_UNLOCK(tty_mgmt_info[device].spinLock);
+    tty_mgmt_info[device].conv_tx_cb = NULL;
+    tty_mgmt_info[device].conv_rx_cb = NULL;    
+    tty_mgmt_info[device].flush_tx = 0;
+    tty_mgmt_info[device].flush_rx = 0;
+    tty_mgmt_info[device].no_indication = 0;
+
+    if (TTY_IS_CONVENTIONAL_TX(device) && TTY_IS_CONVENTIONAL_RX(device)) {
+        tty_mgmt_info[device].init_by_new_mod = 0;
+    }
+    
+    /* Send SIO_CMD_OPEN command */
+    /* 20130313: If driver is not active, store SIO_CMD_OPEN and then return */
+    if(tty_mgmt_info[device].active)
+    {
+        uCtlOpen.u4OwenrId = module_id;
+        status = DclSerialPort_Control(handle, SIO_CMD_OPEN, (DCL_CTRL_DATA_T*)&uCtlOpen);
+        if (STATUS_OK != status) {
+            return status;
+        }
+    }
+    else
+    {
+        TTY_SPIN_LOCK(tty_mgmt_info[device].spinLock);
+        tty_mgmt_info[device].early_open_req = 1;
+        tty_mgmt_info[device].pending_owner = module_id;
+        TTY_SPIN_UNLOCK(tty_mgmt_info[device].spinLock);
+        return STATUS_OK;
+    }
+
+    return STATUS_OK;
+}
+
+static DCL_STATUS DEVDRV_LS_DRAM_EX_ROCODE
+_DclSerialPort_UpModuleReinit(
+    DCL_DEV             device,
+    module_type         module_id,
+    int                 flag)
+{
+    DCL_STATUS result;
+    UART_CTRL_CLR_BUFFER_T ur_ctrl_clr_buf;
+    DCL_UINT32 count;
+    SeriPort_HANLDER_CB sp_handler_cb;
+
+    /*
+     * Notes: if device is buffer port, just reset the ttycore internal flag,
+     *        because it is impossible to use gpd buffer on buffer port
+     */
+    if(TTY_IS_BUFF_PORT(device))
+    {
+        goto _RESET_FLAG;
+    }
+
+    /* If primary module uses conventional Rx and new module uses new rx path, flush Rx data path */
+    TTY_SPIN_LOCK(tty_mgmt_info[device].spinLock);
+    if (TTY_IS_CONVENTIONAL_RX(device) && 
+        tty_mgmt_info[device].rx_gpd_num_assigned > 0 &&
+        (flag & TTY_FLAG_NEW_RX)
+        )
+    {
+
+
+        /* -- 1. Send clear rx buffer command -- */
+        ur_ctrl_clr_buf.u4OwenrId = tty_mgmt_info[device].owner_id;
+        tty_mgmt_info[device].flush_rx = 1;
+        if (!tty_mgmt_info[device].sp_handler_cb) {
+            if(INT_QueryExceptionStatus() == KAL_FALSE)
+            MD_TRC(TTY_TR_DRV_CB_IS_NULL,device, kal_get_active_module_id());
+            TTY_SPIN_UNLOCK(tty_mgmt_info[device].spinLock);  
+            return STATUS_FAIL;
+        }
+        sp_handler_cb = tty_mgmt_info[device].sp_handler_cb;   
+        TTY_SPIN_UNLOCK(tty_mgmt_info[device].spinLock);
+        result = sp_handler_cb(device, SIO_CMD_CLR_RX_BUF, (DCL_CTRL_DATA_T*)&ur_ctrl_clr_buf);
+        if (result != STATUS_OK) {
+            /* command failed */
+            if(INT_QueryExceptionStatus() == KAL_FALSE)
+MD_TRC(TTY_TR_CMD_ERR_CLR_RX_BUF,device, result, kal_get_active_module_id());
+            return result;
+        }
+
+        /* -- 2. Wait until all rx gpds are returned back -- */
+        TTY_CONV_FLUSH_RX(10);
+    } else {
+        TTY_SPIN_UNLOCK(tty_mgmt_info[device].spinLock);
+    }
+
+_RESET_FLAG:
+    tty_mgmt_info[device].owner_id = module_id;
+    tty_mgmt_info[device].flag = flag;
+    tty_mgmt_info[device].rx_gpd = NULL;
+    tty_mgmt_info[device].rx_buf_offset = 0;
+    TTY_SPIN_LOCK(tty_mgmt_info[device].spinLock);
+    tty_mgmt_info[device].tx_gpd_num_used = 0;
+    tty_mgmt_info[device].tx_up_mod_wait = 0;
+    TTY_SPIN_UNLOCK(tty_mgmt_info[device].spinLock);
+    tty_mgmt_info[device].conv_tx_cb = NULL;
+    tty_mgmt_info[device].conv_rx_cb = NULL;
+    tty_mgmt_info[device].flush_tx = 0;
+    tty_mgmt_info[device].flush_rx = 0;
+    tty_mgmt_info[device].no_indication = 0;
+
+    if (TTY_IS_CONVENTIONAL_TX(device) && TTY_IS_CONVENTIONAL_RX(device)) {
+        tty_mgmt_info[device].init_by_new_mod = 0;
+    } else {
+        tty_mgmt_info[device].init_by_new_mod = 1;
+    }
+
+    return STATUS_OK;
+}
+
+/* Re-init API is invoked when New upper module change owner -> it need re-set flag and re-register related callback function */
+/* This API must be called after SIO_CMD_SET_OWNER command */
+DCL_STATUS DEVDRV_LS_DRAM_EX_ROCODE
+DclSerialPort_UpModuleReinit(
+    DCL_HANDLE          handle,
+    module_type         module_id,
+    int                 flag)
+{
+    DCL_DEV device;
+
+    TTY_CHECK_HANDLE(handle);
+    device = DCL_UART_GET_DEV(handle);
+    TTY_CHECK_DEV_IS_READY(device);
+
+    if(INT_QueryExceptionStatus() == KAL_FALSE) 
+MD_TRC(TTY_TR_REINIT,device, module_id);
+
+    if (!tty_mgmt_info[device].opened) {
+        return STATUS_NOT_OPENED;
+    }
+
+    return _DclSerialPort_UpModuleReinit(device, module_id, flag);
+}
+
+
+DCL_STATUS DEVDRV_LS_DRAM_EX_ROCODE
+DclSerialPort_UpModuleDeinit(
+    DCL_HANDLE          handle)
+{
+    DCL_STATUS status = STATUS_FAIL;
+    DCL_DEV device;
+    UART_CTRL_CLOSE_T data;
+
+    TTY_CHECK_HANDLE(handle);
+    device = DCL_UART_GET_DEV(handle);
+    
+    /*20130313:remove driver active check, because user may do initial flow before driver in active state*/
+    TTY_CHECK_DEV_VALID(device);
+ 
+    if(INT_QueryExceptionStatus() == KAL_FALSE) 
+MD_TRC(TTY_TR_DEINIT,device, kal_get_active_module_id());
+
+    TTY_SPIN_LOCK(tty_mgmt_info[device].spinLock);
+    if (!tty_mgmt_info[device].opened && !tty_mgmt_info[device].early_open_req) {
+        TTY_SPIN_UNLOCK(tty_mgmt_info[device].spinLock);
+        if(INT_QueryExceptionStatus() == KAL_FALSE) 
+MD_TRC(TTY_TR_DEV_IS_NOT_OPENED,device, kal_get_active_module_id());
+        return STATUS_NOT_OPENED;
+    }
+    TTY_SPIN_UNLOCK(tty_mgmt_info[device].spinLock);
+
+    /* Send SIO_CMD_CLOSE command */
+    data.u4OwenrId = tty_mgmt_info[device].owner_id;
+    status = DclSerialPort_Control(handle, SIO_CMD_CLOSE, (DCL_CTRL_DATA_T*)&data);
+
+    return status;
+}
+
+static DCL_STATUS DEVDRV_LS_DRAM_EX_ROCODE
+_DclSerialPort_UpModuleRegisterCb(
+    DCL_DEV             device,
+    tty_rx_cb           rx_cb,
+    tty_txdone_cb       tx_done_cb,
+    tty_drv_state_change_cb drv_state_change_cb)
+{
+    DCL_STATUS result;
+    SeriPort_HANLDER_CB sp_handler_cb;
+
+    tty_mgmt_info[device].rx_cb = rx_cb;
+    tty_mgmt_info[device].tx_done_cb = tx_done_cb;  
+    tty_mgmt_info[device].drv_state_change_cb = drv_state_change_cb;
+
+    TTY_SPIN_LOCK(tty_mgmt_info[device].spinLock);
+    if(!tty_mgmt_info[device].active && tx_done_cb)
+    {
+        tty_mgmt_info[device].early_tx_done_cb_req = 1;
+        TTY_SPIN_UNLOCK(tty_mgmt_info[device].spinLock);
+        return STATUS_OK;
+    }
+    else
+    {
+        TTY_SPIN_UNLOCK(tty_mgmt_info[device].spinLock);
+    }
+
+    /* Send TTY_CMD_TX_INFO command */
+    if (tx_done_cb)
+    {
+        UART_CTRL_NEED_TX_DONE_CB_T ur_ctrl_need_tx_done_cb;
+        
+        ur_ctrl_need_tx_done_cb.u4OwnerId = tty_mgmt_info[device].owner_id;
+        ur_ctrl_need_tx_done_cb.needTxDoneCb = 1;
+        TTY_SPIN_LOCK(tty_mgmt_info[device].spinLock);
+        if (!tty_mgmt_info[device].sp_handler_cb) {
+            if(INT_QueryExceptionStatus() == KAL_FALSE)
+            MD_TRC(TTY_TR_DRV_CB_IS_NULL,device, kal_get_active_module_id());
+            TTY_SPIN_UNLOCK(tty_mgmt_info[device].spinLock);  
+            return STATUS_FAIL;
+        }
+        sp_handler_cb = tty_mgmt_info[device].sp_handler_cb;
+        TTY_SPIN_UNLOCK(tty_mgmt_info[device].spinLock);
+        result = sp_handler_cb(device, TTY_CMD_NEED_TX_DONE_CB, (DCL_CTRL_DATA_T*)&ur_ctrl_need_tx_done_cb);
+        if (result != STATUS_OK) {
+            /* command failed */
+            if(INT_QueryExceptionStatus() == KAL_FALSE)
+MD_TRC(TTY_TR_CMD_ERR_NEED_TX_DONE_CB,device, result, kal_get_active_module_id());
+            return result;
+        }
+    }
+
+    return STATUS_OK;
+}
+
+DCL_STATUS DEVDRV_LS_DRAM_EX_ROCODE
+DclSerialPort_UpModuleRegisterCb(
+    DCL_HANDLE          handle,
+    tty_rx_cb           rx_cb,
+    tty_txdone_cb       tx_done_cb,
+    tty_drv_state_change_cb drv_state_change_cb)
+{
+    DCL_DEV device;
+    DCL_STATUS result;
+
+    TTY_CHECK_HANDLE(handle);
+    device = DCL_UART_GET_DEV(handle);
+
+    /*20130313:remove driver active check, because user may do initial flow before driver in active state*/
+    TTY_CHECK_DEV_VALID(device);
+    if(INT_QueryExceptionStatus() == KAL_FALSE)
+MD_TRC(TTY_TR_CMD_REG_CB,device, kal_get_active_module_id());
+ 
+    /* Check flag & callback correctness */
+    if (!TTY_IS_CONVENTIONAL_RX(device) && !rx_cb) {
+        if(INT_QueryExceptionStatus() == KAL_FALSE)
+MD_TRC(TTY_TR_NEW_RX_CB_IS_NULL,device, kal_get_active_module_id());
+        VAR_MSG_ASSERT(use_new_rx_but_not_register_cb);
+    }   
+    if (TTY_IS_CONVENTIONAL_RX(device)) {
+        ASSERT(!rx_cb);
+
+        /* Buffer port use different internal callback*/
+        if(TTY_IS_BUFF_PORT(device))
+        {
+            rx_cb = _tty_rx_buff_cb;
+        }
+        else
+        {
+            rx_cb = _tty_rx_cb;
+        }
+    }
+    if (TTY_IS_CONVENTIONAL_TX(device)) {
+        ASSERT(!tx_done_cb);
+
+        /* Buffer port use different internal callback*/
+        if(TTY_IS_BUFF_PORT(device))
+        {
+            tx_done_cb = _tty_tx_buff_done_cb;
+        }
+        else
+        {
+            tx_done_cb = _tty_tx_done_cb;
+        }
+    }
+    
+    if (TTY_IS_CONVENTIONAL_RX(device) && TTY_IS_CONVENTIONAL_TX(device)) {
+        ASSERT(!drv_state_change_cb);
+    } else {
+        ASSERT(drv_state_change_cb);
+    }
+
+    result = _DclSerialPort_UpModuleRegisterCb(device, rx_cb, tx_done_cb, drv_state_change_cb);
+    if (result != STATUS_OK) {
+        /* command failed */
+        if(INT_QueryExceptionStatus() == KAL_FALSE)
+MD_TRC(TTY_TR_CMD_REG_CB_FAIL,device, result, kal_get_active_module_id());
+        return result;
+    }   
+
+    return STATUS_OK;
+}
+
+DCL_STATUS DEVDRV_LS_DRAM_EX_ROCODE
+DclSerialPort_UpModuleTransmit(
+    DCL_HANDLE          handle,
+    tty_io_request_t    *ior)
+{
+    DCL_DEV device;
+    UART_CTRL_PUT_BYTES_IOR_T ur_ctrl_putbytes_ior;
+    DCL_STATUS result;
+    SeriPort_HANLDER_CB sp_handler_cb;
+        
+    TTY_CHECK_HANDLE(handle);
+    device = DCL_UART_GET_DEV(handle);
+    DBG_ASSERT(ior);
+
+    TTY_SPIN_LOCK(tty_mgmt_info[device].spinLock);
+    if (!tty_mgmt_info[device].sp_handler_cb) {       
+        if(INT_QueryExceptionStatus() == KAL_FALSE)
+        MD_TRC(TTY_TR_DRV_CB_IS_NULL,device, kal_get_active_module_id());
+        TTY_SPIN_UNLOCK(tty_mgmt_info[device].spinLock);  
+        return STATUS_FAIL;
+    }
+
+    
+
+    if (!TTY_CHK_DEV_OPEN(device)){
+        TTY_SPIN_UNLOCK(tty_mgmt_info[device].spinLock);
+        return STATUS_NOT_OPENED;
+    }
+
+    ur_ctrl_putbytes_ior.u4OwnerId = tty_mgmt_info[device].owner_id;
+    ur_ctrl_putbytes_ior.putIor = (void*)ior;
+    sp_handler_cb = tty_mgmt_info[device].sp_handler_cb;
+    TTY_SPIN_UNLOCK(tty_mgmt_info[device].spinLock);
+    result = sp_handler_cb(device, TTY_CMD_PUT_BYTES_IOR, (DCL_CTRL_DATA_T*)&ur_ctrl_putbytes_ior);
+
+#ifdef __TTY_DBG_MODE__
+    _tty_gpd_zero_len_check(ior);
+#endif
+
+    return result;
+}
+
+DCL_STATUS DEVDRV_LS_DRAM_EX_ROCODE
+DclSerialPort_UpModuleTransmitLight(
+    DCL_HANDLE          handle,
+    tty_io_request_t    *ior)
+{
+    DCL_DEV device;
+    UART_CTRL_PUT_BYTES_IOR_T ur_ctrl_putbytes_ior;
+    DCL_STATUS result;
+    SeriPort_HANLDER_CB sp_handler_cb;
+
+    TTY_CHECK_HANDLE(handle);
+    device = DCL_UART_GET_DEV(handle);
+    DBG_ASSERT(ior);
+    
+    TTY_SPIN_LOCK(tty_mgmt_info[device].spinLock);
+    if (!tty_mgmt_info[device].sp_handler_cb) {
+        if(INT_QueryExceptionStatus() == KAL_FALSE)
+            MD_TRC(TTY_TR_DRV_CB_IS_NULL,device, kal_get_active_module_id());
+        TTY_SPIN_UNLOCK(tty_mgmt_info[device].spinLock);  
+        return STATUS_FAIL;
+    }
+    
+    ur_ctrl_putbytes_ior.u4OwnerId = tty_mgmt_info[device].owner_id;
+    ur_ctrl_putbytes_ior.putIor = (void*)ior;
+
+#ifdef __TTY_DBG_MODE__
+    _tty_gpd_zero_len_check(ior);
+#endif
+    sp_handler_cb = tty_mgmt_info[device].sp_handler_cb;
+    TTY_SPIN_UNLOCK(tty_mgmt_info[device].spinLock);
+    result = sp_handler_cb(device, TTY_CMD_PUT_BYTES_IOR_LIGHT, (DCL_CTRL_DATA_T*)&ur_ctrl_putbytes_ior);
+    return result;
+}
+
+DCL_STATUS DEVDRV_LS_DRAM_EX_ROCODE
+DclSerialPort_UpModuleAssignRxIor(
+    DCL_HANDLE          handle,
+    tty_io_request_t    *rx_ior)
+{
+    DCL_DEV device;
+    UART_CTRL_ASSIGN_RX_IOR_T uartCtlAsnRxIor;
+    DCL_STATUS result;
+    SeriPort_HANLDER_CB sp_handler_cb;
+    
+    TTY_CHECK_HANDLE(handle);
+    device = DCL_UART_GET_DEV(handle);
+    DBG_ASSERT(rx_ior);
+
+    if(INT_QueryExceptionStatus() == KAL_FALSE)
+MD_TRC(TTY_TR_CMD_ASSIGN_RX_IOR,device, kal_get_active_module_id());
+    TTY_SPIN_LOCK(tty_mgmt_info[device].spinLock);
+    if (!tty_mgmt_info[device].sp_handler_cb) { 
+        if(INT_QueryExceptionStatus() == KAL_FALSE)
+        MD_TRC(TTY_TR_DRV_CB_IS_NULL,device, kal_get_active_module_id());
+        TTY_SPIN_UNLOCK(tty_mgmt_info[device].spinLock);  
+        return STATUS_FAIL;
+    }
+
+    uartCtlAsnRxIor.u4OwnerId = tty_mgmt_info[device].owner_id;
+    uartCtlAsnRxIor.ior = (void*)rx_ior;
+    sp_handler_cb = tty_mgmt_info[device].sp_handler_cb;
+    TTY_SPIN_UNLOCK(tty_mgmt_info[device].spinLock);
+    result = sp_handler_cb(device, TTY_CMD_ASSIGN_RX_IOR, (DCL_CTRL_DATA_T*)&uartCtlAsnRxIor);
+    
+    return result;
+}
+
+
+DCL_STATUS DEVDRV_LS_DRAM_EX_ROCODE
+DclSerialPort_DrvRegisterCb(
+    DCL_HANDLE          handle,
+    Seriport_HANDLER_T* seriport_handler)
+{
+    DCL_DEV device;
+    UART_CTRL_OPEN_T uCtlOpen;
+    UART_CTRL_NEED_TX_DONE_CB_T ur_ctrl_need_tx_done_cb;
+    DCL_STATUS status;
+    SeriPort_HANLDER_CB sp_handler_cb;
+    
+    TTY_CHECK_HANDLE(handle);
+    device = DCL_UART_GET_DEV(handle);
+
+    if(INT_QueryExceptionStatus() == KAL_FALSE)
+MD_TRC(TTY_TR_DRV_REGISTER_CB,device, seriport_handler, kal_get_active_module_id());
+
+    if (!seriport_handler->SeriportHandlerCb) {
+        if(INT_QueryExceptionStatus() == KAL_FALSE)
+MD_TRC(TTY_TR_DRV_CB_IS_NULL,device, kal_get_active_module_id());
+        ASSERT(seriport_handler->SeriportHandlerCb);
+        return STATUS_INVALID_ARGUMENT;
+    }
+
+    if (tty_mgmt_info[device].active) {
+        return STATUS_ALREADY_OPENED;
+    }
+    
+    TTY_SPIN_LOCK(tty_mgmt_info[device].spinLock);
+    tty_mgmt_info[device].sp_handler_cb = seriport_handler->SeriportHandlerCb;
+    TTY_SPIN_UNLOCK(tty_mgmt_info[device].spinLock);
+    
+    tty_mgmt_info[device].dev_type = seriport_handler->DevType;
+    _tty_update_buff_info_from_port(device, seriport_handler->DevType);
+
+    //Must to put at the end of function.
+    tty_mgmt_info[device].active = 1;
+
+    //------------------------------------------------------------------//
+    //check if user has opened the port before driver register callback //
+    
+    TTY_SPIN_LOCK(tty_mgmt_info[device].spinLock);
+    if(tty_mgmt_info[device].early_open_req)
+    {
+        tty_mgmt_info[device].early_open_req = 0;
+        TTY_SPIN_UNLOCK(tty_mgmt_info[device].spinLock);
+        uCtlOpen.u4OwenrId = tty_mgmt_info[device].pending_owner;
+        //temp for uart
+        //DclSerialPort_Control(handle,SIO_CMD_INIT,(DCL_CTRL_DATA_T*)&uCtlOpen);
+        status = DclSerialPort_Control(handle, SIO_CMD_OPEN, (DCL_CTRL_DATA_T*)&uCtlOpen);
+        if (STATUS_OK != status) {
+            //ASSERT(0);
+            return status;
+        }
+    }
+    else
+    {
+        TTY_SPIN_UNLOCK(tty_mgmt_info[device].spinLock);
+    }
+    
+    TTY_SPIN_LOCK(tty_mgmt_info[device].spinLock);
+    if(tty_mgmt_info[device].early_tx_done_cb_req)
+    {
+        tty_mgmt_info[device].early_tx_done_cb_req = 0;
+        ur_ctrl_need_tx_done_cb.u4OwnerId = tty_mgmt_info[device].owner_id;
+        ur_ctrl_need_tx_done_cb.needTxDoneCb = 1;
+        sp_handler_cb = tty_mgmt_info[device].sp_handler_cb;
+        TTY_SPIN_UNLOCK(tty_mgmt_info[device].spinLock);
+        status = sp_handler_cb(device, TTY_CMD_NEED_TX_DONE_CB, (DCL_CTRL_DATA_T*)&ur_ctrl_need_tx_done_cb);
+        if (status != STATUS_OK) {
+            /* command failed */
+            if(INT_QueryExceptionStatus() == KAL_FALSE)
+MD_TRC(TTY_TR_CMD_ERR_NEED_TX_DONE_CB,device, status, kal_get_active_module_id());
+            return status;
+        }
+    }
+    else
+    {
+        TTY_SPIN_UNLOCK(tty_mgmt_info[device].spinLock);
+    }
+    return STATUS_OK;
+}
+
+DCL_STATUS DEVDRV_LS_DRAM_EX_ROCODE
+DclSerialPort_DrvDeRegisterCb(
+    DCL_HANDLE          handle)
+{
+    DCL_DEV device;
+    //TTY_THREAD_DECLARE(thread_lock);
+
+    TTY_CHECK_HANDLE(handle);
+    device = DCL_UART_GET_DEV(handle);
+
+    if(INT_QueryExceptionStatus() == KAL_FALSE)
+MD_TRC(TTY_TR_DRV_DEREGISTER_CB,device, kal_get_active_module_id());
+
+    if(tty_mgmt_info[device].drv_state == DRV_ST_ATTACHED)
+    {
+        return STATUS_INVALID_OPERATION;
+    }
+
+    if (!tty_mgmt_info[device].active) {
+        return STATUS_INVALID_OPERATION;
+    }
+    
+   /*Enlarge spinlock in order to protect the handler pointer */
+    TTY_SPIN_LOCK(tty_mgmt_info[device].spinLock);
+    /* Clear flags */
+    tty_mgmt_info[device].active = 0;
+    tty_mgmt_info[device].sp_handler_cb = NULL;
+
+    /***** Add for USB CV test *****/
+    /* Check device state */
+    /* Here we slient clear opened flag if the device is opened 
+       After driver registered the device, tty will re-open the device
+    */
+    if(tty_mgmt_info[device].opened)
+    {
+
+        tty_mgmt_info[device].opened = 0;
+        tty_mgmt_info[device].early_open_req = 1;
+        tty_mgmt_info[device].pending_owner = tty_mgmt_info[device].owner_id;
+        if(tty_mgmt_info[device].tx_done_cb)
+        {
+            tty_mgmt_info[device].early_tx_done_cb_req = 1;
+        }
+    }
+    TTY_SPIN_UNLOCK(tty_mgmt_info[device].spinLock);
+    /***** Add for USB CV test *****/
+    
+    return STATUS_OK;
+}
+
+
+DCL_STATUS DEVDRV_LS_DRAM_EX_ROCODE
+DclSerialPort_DrvAttach(
+    DCL_HANDLE          handle)
+{
+    DCL_DEV device;
+    DCL_STATUS result;
+    UART_CTRL_GET_CHUNK_SIZE_T ur_ctrl_get_chunk_size;
+     SeriPort_HANLDER_CB sp_handler_cb;
+
+    TTY_CHECK_HANDLE(handle);
+    device = DCL_UART_GET_DEV(handle);
+    TTY_CHECK_DEV_IS_READY(device);
+
+    if(INT_QueryExceptionStatus() == KAL_FALSE) 
+MD_TRC(TTY_TR_DRV_ATTACH,device, kal_get_active_module_id());
+
+    tty_mgmt_info[device].drv_state = DRV_ST_ATTACHED;
+
+    if(TTY_IS_BUFF_PORT(device))
+    {
+        /* Set default value align with USB, although buffer port does not reference this value*/
+        tty_mgmt_info[device].chunk_size = 512;
+        goto _RETURN;
+    }
+    TTY_SPIN_LOCK(tty_mgmt_info[device].spinLock);
+    if (!tty_mgmt_info[device].sp_handler_cb) {
+        if(INT_QueryExceptionStatus() == KAL_FALSE)
+        MD_TRC(TTY_TR_DRV_CB_IS_NULL,device, kal_get_active_module_id());
+        TTY_SPIN_UNLOCK(tty_mgmt_info[device].spinLock);
+        return STATUS_FAIL;
+    }  
+    sp_handler_cb = tty_mgmt_info[device].sp_handler_cb;        
+    TTY_SPIN_UNLOCK(tty_mgmt_info[device].spinLock);
+    result = sp_handler_cb(device, TTY_CMD_GET_CHUNK_SIZE, (DCL_CTRL_DATA_T*)&ur_ctrl_get_chunk_size);
+    
+    if (result != STATUS_OK) {
+        /* command failed */
+        if(INT_QueryExceptionStatus() == KAL_FALSE)
+MD_TRC(TTY_TR_CMD_ERR_GET_CHUNK_SIZE,device, result, kal_get_active_module_id());
+        ASSERT(0);
+        return result;
+    }
+    
+    tty_mgmt_info[device].chunk_size = (DCL_UINT16)ur_ctrl_get_chunk_size.chunkSize;
+    //set rx allow len
+    _cal_and_set_rx_allow_len(device, tty_mgmt_info[device].chunk_size);
+
+    if (tty_mgmt_info[device].opened)
+    {
+        /* Notify upper layer the driver status is attached */
+        if (tty_mgmt_info[device].drv_state_change_cb) {
+            tty_mgmt_info[device].drv_state_change_cb(handle, DRV_ST_ATTACHED);
+        }
+        
+        if (TTY_IS_CONVENTIONAL_RX(device)) {
+            _tty_conv_assign_rx_gpd_to_drv(device);
+        }
+
+        if (TTY_IS_CONVENTIONAL_TX(device))
+        {
+            TTY_SPIN_LOCK(tty_mgmt_info[device].spinLock);
+            if(tty_mgmt_info[device].tx_not_rdy == 1)
+            {
+                tty_mgmt_info[device].tx_not_rdy = 0;
+                TTY_SPIN_UNLOCK(tty_mgmt_info[device].spinLock);
+                _tty_send_ilm(device, MOD_TTY, MSG_ID_UART_READY_TO_WRITE_IND);
+            }
+            else
+            {
+                TTY_SPIN_UNLOCK(tty_mgmt_info[device].spinLock);
+            }
+        }
+    }
+    
+_RETURN:
+    return STATUS_OK;
+}
+
+DCL_STATUS DEVDRV_LS_DRAM_EX_ROCODE
+DclSerialPort_DrvDetach(
+    DCL_HANDLE          handle)
+{
+    DCL_DEV device;
+    DCL_STATUS result;
+    UART_CTRL_CLR_BUFFER_T ur_ctrl_clr_buf;
+    SeriPort_HANLDER_CB sp_handler_cb;
+    
+    TTY_CHECK_HANDLE(handle);
+    device = DCL_UART_GET_DEV(handle);
+    TTY_CHECK_DEV_IS_READY(device);
+
+    if(INT_QueryExceptionStatus() == KAL_FALSE) 
+MD_TRC(TTY_TR_DRV_DETACH,device, kal_get_active_module_id());
+
+    tty_mgmt_info[device].drv_state = DRV_ST_DETACHED;
+
+    /* Notify upper layer the driver status is detached */
+    if (tty_mgmt_info[device].opened)
+    {
+        if (tty_mgmt_info[device].drv_state_change_cb) {
+            tty_mgmt_info[device].drv_state_change_cb(handle, DRV_ST_DETACHED);
+        }
+        
+        /* Send clear tx/rx buffer command */
+        ur_ctrl_clr_buf.u4OwenrId = tty_mgmt_info[device].owner_id;
+
+        /* Buffer port also needs to do flush when detached */
+        TTY_SPIN_LOCK(tty_mgmt_info[device].spinLock);
+        if ((tty_mgmt_info[device].tx_gpd_num_used != 0 && TTY_IS_CONVENTIONAL_TX(device)) 
+            || TTY_IS_BUFF_PORT(device) )
+        {
+            TTY_SPIN_UNLOCK(tty_mgmt_info[device].spinLock);
+
+            /* Only GPD driver needs to toggle this flag*/
+            if(!TTY_IS_BUFF_PORT(device))
+            {
+                tty_mgmt_info[device].flush_tx = 1;
+            }
+            TTY_SPIN_LOCK(tty_mgmt_info[device].spinLock);
+            if (!tty_mgmt_info[device].sp_handler_cb) {
+                if(INT_QueryExceptionStatus() == KAL_FALSE)
+                MD_TRC(TTY_TR_DRV_CB_IS_NULL,device, kal_get_active_module_id());
+                TTY_SPIN_UNLOCK(tty_mgmt_info[device].spinLock);
+                return STATUS_FAIL;
+            }
+            sp_handler_cb = tty_mgmt_info[device].sp_handler_cb; 
+            TTY_SPIN_UNLOCK(tty_mgmt_info[device].spinLock);
+            result = sp_handler_cb(device, SIO_CMD_CLR_TX_BUF, (DCL_CTRL_DATA_T*)&ur_ctrl_clr_buf);
+            if (result != STATUS_OK) {
+                /* command failed */
+                if(INT_QueryExceptionStatus() == KAL_FALSE)
+MD_TRC(TTY_TR_CMD_ERR_CLR_TX_BUF,device, result, kal_get_active_module_id());
+                return result;
+            }
+        } else {
+            TTY_SPIN_UNLOCK(tty_mgmt_info[device].spinLock);
+        }
+
+        /* Buffer port also needs to do flush when detached */
+        TTY_SPIN_LOCK(tty_mgmt_info[device].spinLock);
+        if ((tty_mgmt_info[device].rx_gpd_num_assigned != 0 && TTY_IS_CONVENTIONAL_RX(device))
+            || TTY_IS_BUFF_PORT(device) )
+        {
+            TTY_SPIN_UNLOCK(tty_mgmt_info[device].spinLock);
+            
+            /* Only GPD driver needs to toggle this flag*/
+            if(!TTY_IS_BUFF_PORT(device))
+            {
+                tty_mgmt_info[device].flush_rx = 1;
+            }
+            TTY_SPIN_LOCK(tty_mgmt_info[device].spinLock);
+            if (!tty_mgmt_info[device].sp_handler_cb) {
+                if(INT_QueryExceptionStatus() == KAL_FALSE)
+                MD_TRC(TTY_TR_DRV_CB_IS_NULL,device, kal_get_active_module_id());
+                TTY_SPIN_UNLOCK(tty_mgmt_info[device].spinLock);
+                return STATUS_FAIL;
+            }
+            sp_handler_cb = tty_mgmt_info[device].sp_handler_cb;
+            TTY_SPIN_UNLOCK(tty_mgmt_info[device].spinLock);
+            result = sp_handler_cb(device, SIO_CMD_CLR_RX_BUF, (DCL_CTRL_DATA_T*)&ur_ctrl_clr_buf);
+            if (result != STATUS_OK) {
+                /* command failed */
+                if(INT_QueryExceptionStatus() == KAL_FALSE)
+MD_TRC(TTY_TR_CMD_ERR_CLR_RX_BUF,device, result, kal_get_active_module_id());
+                return result;
+            }
+        } else {
+            TTY_SPIN_UNLOCK(tty_mgmt_info[device].spinLock);
+        }
+    }   
+
+    return STATUS_OK;
+}
+
+DCL_STATUS DEVDRV_LS_DRAM_EX_ROCODE
+DclSerialPort_DrvRx(
+    DCL_HANDLE          handle,
+    module_type         source_id,
+    void                *rx_ior)
+{
+    DCL_DEV device;
+
+    TTY_CHECK_HANDLE(handle);
+    device = DCL_UART_GET_DEV(handle);
+
+    if (tty_mgmt_info[device].opened && tty_mgmt_info[device].rx_cb) {
+        tty_mgmt_info[device].rx_cb(handle, source_id, (tty_io_request_t*)rx_ior);
+    } else {
+        if(INT_QueryExceptionStatus() == KAL_FALSE)
+MD_TRC(TTY_TR_DRV_RX_NG,device, tty_mgmt_info[device].opened, tty_mgmt_info[device].rx_cb);
+        /* Free ior when the device is closed */
+        if(!TTY_IS_BUFF_PORT(device))
+        {
+            _tty_free_ior(rx_ior);
+        }   
+    }
+    return STATUS_OK;
+}
+
+DCL_STATUS DEVDRV_LS_DRAM_EX_ROCODE
+DclSerialPort_DrvTxDone(
+    DCL_HANDLE          handle,
+    module_type         source_id,
+    void                *tx_ior)
+{
+    DCL_DEV device;
+
+    TTY_CHECK_HANDLE(handle);
+    device = DCL_UART_GET_DEV(handle);
+
+    if (tty_mgmt_info[device].opened && tty_mgmt_info[device].tx_done_cb) {
+        tty_mgmt_info[device].tx_done_cb(handle, source_id, (tty_io_request_t*)tx_ior);
+    } else {
+        /* Free ior when the device is closed */
+        if(!TTY_IS_BUFF_PORT(device))
+        {
+            _tty_free_ior(tx_ior);
+        }
+    }
+
+    return STATUS_OK;
+}
+
+