[Feature]Upload Modem source code

Change-Id: Id4294f30faced84d3e6fd6d5e61e1111bf287a37
diff --git a/mcu/driver/tty/inc/tty_trace.h b/mcu/driver/tty/inc/tty_trace.h
new file mode 100644
index 0000000..493a4df
--- /dev/null
+++ b/mcu/driver/tty/inc/tty_trace.h
@@ -0,0 +1,17 @@
+#ifndef _TTY_TRACE_H_
+#define _TTY_TRACE_H_
+#if TTY_CONSOLE_TRACE_ENABLED != 1
+#ifndef GEN_FOR_PC
+ #include "stack_config.h"
+#endif /* GEN_FOR_PC */
+#include "dhl_trace.h"
+#include "dhl_def.h"
+#if !defined(GEN_FOR_PC)
+#if defined(__DHL_MODULE__) || defined(__CUSTOM_RELEASE__)
+#endif /* TST Trace Defintion */
+#endif
+#endif /* TTY_CONSOLE_TRACE_ENABLED != 1 */
+#if !defined(GEN_FOR_PC)
+#include"tty_trace_mod_tty_utmd.h"
+#endif
+#endif /* _TTY_TRACE_H_ */
diff --git a/mcu/driver/tty/inc/tty_trace_mod_tty_utmd.json b/mcu/driver/tty/inc/tty_trace_mod_tty_utmd.json
new file mode 100644
index 0000000..9d80d88
--- /dev/null
+++ b/mcu/driver/tty/inc/tty_trace_mod_tty_utmd.json
@@ -0,0 +1,278 @@
+{
+  "legacyParameters": {}, 
+  "module": "MOD_TTY", 
+  "startGen": "Legacy",
+  "endGen": "-",
+  "UserModule": "MOD_TTY",
+  "traceFamily": "PS",
+  "traceClassDefs": [
+    {
+      "TRACE_INFO": {
+        "debugLevel": "Medium", 
+        "tag": [
+          "Baseline", 
+          "TRACE_INFO"
+        ], 
+        "traceType": "InternalDesign"
+      }
+    }, 
+    {
+      "TRACE_WARNING": {
+        "debugLevel": "High", 
+        "tag": [
+          "Baseline", 
+          "TRACE_WARNING"
+        ], 
+        "traceType": "InternalDesign"
+      }
+    }, 
+    {
+      "TRACE_ERROR": {
+        "debugLevel": "Ultra-High", 
+        "tag": [
+          "Baseline", 
+          "TRACE_ERROR"
+        ], 
+        "traceType": "InternalDesign"
+      }
+    }, 
+    {
+      "TRACE_FUNC": {
+        "debugLevel": "Medium", 
+        "tag": [
+          "Baseline", 
+          "TRACE_FUNC"
+        ], 
+        "traceType": "CoreDesign"
+      }
+    }, 
+    {
+      "TRACE_STATE": {
+        "debugLevel": "Low", 
+        "tag": [
+          "Baseline", 
+          "TRACE_STATE"
+        ], 
+        "traceType": "CoreDesign"
+      }
+    }
+  ], 
+  "traceDefs": [
+    {
+      "TTY_TR_OPEN_ERR": {
+        "format": "[TTY] [Dev: %d] DclSerialPort_Open error, module_id: %Mmodule_type", 
+        "traceClass": "TRACE_ERROR"
+      }
+    }, 
+    {
+      "TTY_TR_CMD_OPEN_ALREADY_OPENED": {
+        "format": "[TTY] [Dev: %d] Device is already opened. (module_id: %Mmodule_type)", 
+        "traceClass": "TRACE_WARNING"
+      }
+    }, 
+    {
+      "TTY_TR_DEV_IS_NOT_OPENED": {
+        "format": "[TTY] [Dev: %d] Device is not opened. (module_id: %Mmodule_type)", 
+        "traceClass": "TRACE_WARNING"
+      }
+    }, 
+    {
+      "TTY_TR_DEV_DRV_NOT_RDY": {
+        "format": "[TTY] [Line: %d] [Dev: %d] Device driver doesn't register CB, (module_id: %Mmodule_type)", 
+        "traceClass": "TRACE_ERROR"
+      }
+    }, 
+    {
+      "TTY_TR_DEV_NOT_VALID": {
+        "format": "[TTY] [Line: %d] [Dev: %d] Device is invalid, (module_id: %Mmodule_type)", 
+        "traceClass": "TRACE_ERROR"
+      }
+    }, 
+    {
+      "TTY_TR_INVALID_HANDLE": {
+        "format": "[TTY] [Line: %d] Invalid handle!, handle = %d, (module_id: %Mmodule_type)", 
+        "traceClass": "TRACE_ERROR"
+      }
+    }, 
+    {
+      "TTY_TR_CONV_INIT": {
+        "format": "[TTY] [Dev: %d] Conventional module open init (module_id: %Mmodule_type)", 
+        "traceClass": "TRACE_FUNC"
+      }
+    }, 
+    {
+      "TTY_TR_NEW_INIT": {
+        "format": "[TTY] [Dev: %d] New module init, (module id: %Mmodule_type)", 
+        "traceClass": "TRACE_FUNC"
+      }
+    }, 
+    {
+      "TTY_TR_REINIT": {
+        "format": "[TTY] [Dev: %d] re-init, new module id: %Mmodule_type ", 
+        "traceClass": "TRACE_FUNC"
+      }
+    }, 
+    {
+      "TTY_TR_DEINIT": {
+        "format": "[TTY] [Dev: %d] de-init, (module_id: %Mmodule_type)", 
+        "traceClass": "TRACE_FUNC"
+      }
+    }, 
+    {
+      "TTY_TR_DRV_ATTACH": {
+        "format": "[TTY] [Dev: %d] Driver attach, (module_id: %Mmodule_type)", 
+        "traceClass": "TRACE_FUNC"
+      }
+    }, 
+    {
+      "TTY_TR_DRV_DETACH": {
+        "format": "[TTY] [Dev: %d] Driver detach, (module_id: %Mmodule_type)", 
+        "traceClass": "TRACE_FUNC"
+      }
+    }, 
+    {
+      "TTY_TR_DRV_REGISTER_CB": {
+        "format": "[TTY] [Dev: %d] Driver register callback function (%p), (module_id: %Mmodule_type)", 
+        "traceClass": "TRACE_FUNC"
+      }
+    }, 
+    {
+      "TTY_TR_DRV_CB_IS_NULL": {
+        "format": "[TTY] [Dev: %d] Driver callback handler is NULL!! (module_id: %Mmodule_type)", 
+        "traceClass": "TRACE_ERROR"
+      }
+    }, 
+    {
+      "TTY_TR_NEW_RX_CB_IS_NULL": {
+        "format": "[TTY] [Dev: %d] Rx use new path but doesn't register callback!! (module_id: %Mmodule_type)", 
+        "traceClass": "TRACE_ERROR"
+      }
+    }, 
+    {
+      "TTY_TR_GPD_EXHAUST": {
+        "format": "[TTY] [Dev: %d] GPD is exhausted!! (module_id: %Mmodule_type)", 
+        "traceClass": "TRACE_WARNING"
+      }
+    }, 
+    {
+      "TTY_TR_TX_IOR_IS_NULL": {
+        "format": "[TTY] [Dev: %d] Tx callback IOR is NULL!! (module_id: %Mmodule_type)", 
+        "traceClass": "TRACE_ERROR"
+      }
+    }, 
+    {
+      "TTY_TR_CMD_ERR_ASSIGN_RX_IOR": {
+        "format": "[TTY] [Dev: %d] Driver Command error : %d !! command: assign rx ior, (module_id: %Mmodule_type)", 
+        "traceClass": "TRACE_WARNING"
+      }
+    }, 
+    {
+      "TTY_TR_CMD_ERR_PUT_BYTES_IOR": {
+        "format": "[TTY] [Dev: %d] Driver Command error : %d !! command: put bytes ior, (module_id: %Mmodule_type)", 
+        "traceClass": "TRACE_WARNING"
+      }
+    }, 
+    {
+      "TTY_TR_CMD_ERR_NEED_TX_DONE_CB": {
+        "format": "[TTY] [Dev: %d] Driver Command error : %d !! command: need tx done cb, (module_id: %Mmodule_type)", 
+        "traceClass": "TRACE_WARNING"
+      }
+    }, 
+    {
+      "TTY_TR_CMD_ERR_GET_CHUNK_SIZE": {
+        "format": "[TTY] [Dev: %d] Command error : %d !! command: get chunk size, (module_id: %Mmodule_type)", 
+        "traceClass": "TRACE_ERROR"
+      }
+    }, 
+    {
+      "TTY_TR_CMD_ERR_CLR_TX_BUF": {
+        "format": "[TTY] [Dev: %d] Command error : %d !! command: clear tx buffer, (module_id: %Mmodule_type)", 
+        "traceClass": "TRACE_WARNING"
+      }
+    }, 
+    {
+      "TTY_TR_CMD_ERR_CLR_RX_BUF": {
+        "format": "[TTY] [Dev: %d] Command error : %d !! command: clear rx buffer, (module_id: %Mmodule_type)", 
+        "traceClass": "TRACE_WARNING"
+      }
+    }, 
+    {
+      "TTY_TR_CMD_REG_CB_FAIL": {
+        "format": "[TTY] [Dev: %d] Command error : %d !! command: register callback, (module_id: %Mmodule_type)", 
+        "traceClass": "TRACE_WARNING"
+      }
+    }, 
+    {
+      "TTY_TR_DRV_DEREGISTER_CB": {
+        "format": "[TTY] [Dev: %d] Driver de-register callback function, (module_id: %Mmodule_type)", 
+        "traceClass": "TRACE_INFO"
+      }
+    }, 
+    {
+      "TTY_TR_CMD_CONV_TX": {
+        "format": "[TTY] [Dev: %d] Command conventional putbytes, length: %d", 
+        "traceClass": "TRACE_INFO"
+      }
+    }, 
+    {
+      "TTY_TR_CMD_CONV_RX": {
+        "format": "[TTY] [Dev: %d] Command conventional getbytes, length: %d", 
+        "traceClass": "TRACE_INFO"
+      }
+    }, 
+    {
+      "TTY_TR_CMD_CONV_TX_NOT_RDY": {
+        "format": "[TTY] [Dev: %d] Command conventional putbytes not ready, tx gpd current used: %d, (module_id: %Mmodule_type)", 
+        "traceClass": "TRACE_INFO"
+      }
+    }, 
+    {
+      "TTY_TR_CMD_DCL_CONTROL": {
+        "format": "[TTY] [Dev: %d] DclSerialPort_Control, command: %d, (module_id: %Mmodule_type)", 
+        "traceClass": "TRACE_FUNC"
+      }
+    }, 
+    {
+      "TTY_TR_WRONG_STATE": {
+        "format": "[TTY] [Dev: %d] Wrong state, driver not attached or flush operation not finished, (module_id: %Mmodule_type)", 
+        "traceClass": "TRACE_WARNING"
+      }
+    }, 
+    {
+      "TTY_TR_CMD_CONV_RX_NOT_RDY": {
+        "format": "[TTY] [Dev: %d] Command conventional getbytes not ready, no available data, (module_id: %Mmodule_type)", 
+        "traceClass": "TRACE_INFO"
+      }
+    }, 
+    {
+      "TTY_TR_CMD_REG_CB": {
+        "format": "[TTY] [Dev: %d] Register user callback, (module_id: %Mmodule_type)", 
+        "traceClass": "TRACE_FUNC"
+      }
+    }, 
+    {
+      "TTY_TR_CMD_ASSIGN_RX_IOR": {
+        "format": "[TTY] [Dev: %d] Command assign RX ior, (module_id: %Mmodule_type)", 
+        "traceClass": "TRACE_FUNC"
+      }
+    }, 
+    {
+      "TTY_TR_DRV_RX_ALLOW_LEN": {
+        "format": "[TTY] [Dev: %d] RX_ALLOW_LEN: %d", 
+        "traceClass": "TRACE_STATE"
+      }
+    }, 
+    {
+      "TTY_TR_DRV_RX_NG": {
+        "format": "[TTY] [Dev: %d] device open state : %d, callback func: %x", 
+        "traceClass": "TRACE_WARNING"
+      }
+    }, 
+    {
+      "TTY_TR_DCL_CMD_NG": {
+        "format": "[TTY] [Dev: %d] command: 0x%x, result: %d", 
+        "traceClass": "TRACE_WARNING"
+      }
+    }
+  ]
+}
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;
+}
+
+
diff --git a/mcu/driver/tty/src/excp_tty_ut.c b/mcu/driver/tty/src/excp_tty_ut.c
new file mode 100644
index 0000000..0dbaa4c
--- /dev/null
+++ b/mcu/driver/tty/src/excp_tty_ut.c
@@ -0,0 +1,767 @@
+/*****************************************************************************
+*  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:
+ * ---------
+ *   excp_tty_ut.c
+ *
+ * Project:
+ * --------
+ *   MOLY
+ *
+ * Description:
+ * ------------
+ *   TTY Core unit test file in exception mode - it needs Host Test Program to run test.
+ *   It works with enabling compile flag __EXCEPT_TTY_UT__.
+ *
+ * Author:
+ * -------
+ * -------
+ *
+ * ==========================================================================
+ * $Log$
+ *
+ * 03 11 2015 i-wei.tsai
+ * [MOLY00097392] [UMOLY] [TTY] Timer tick macro modification
+ * 	.
+ *
+ * 09 13 2013 i-wei.tsai
+ * [MOLY00037205] [CCCI Exception] CCCI exception mode 1st check-in.
+ * 	CCCI Exception IT
+ *
+ * 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
+ *
+ * 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
+ *
+ * 11 12 2012 haoren.kao
+ * [MOLY00005322] TATAKA merge to MOLY
+ * * Shorten the busy loop time from about 5 ms to 10 us in order to avoid host test program SetCommState timeout.
+ ****************************************************************************/
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "dcl.h"
+#include "hmu.h"
+#include "kal_debug.h"
+#include "qmu_bm.h"
+#include "qmu_bm_util.h"
+#include "syscomp_config.h"
+
+#include "devdrv_ls.h"
+#include "drv_msgid.h"
+#include "md_drv_sap.h"
+#include "kal_public_defs.h"
+
+
+//#define __EXPT_CCCI_TTY_IT__
+
+#ifdef __EXPT_CCCI_TTY_IT__
+#define EXCEPTION_TEST_PORT     uart_port_dhl_sp_expt 
+//#define EXCEPTION_TEST_PORT     uart_port_dhl_ctrl_sp_expt
+#else
+#define EXCEPTION_TEST_PORT     uart_port_usb2
+#endif
+#define TX_BUF_NUM              500
+#define RX_BUF_NUM              499+1/*for tailed gpd*/
+#define TEST_LB_PKT_NUM         200
+#define EXCPT_TTY_UT_CHUNK_SIZE_DEFAULT  (QBM_TTY_XXX_DATA_LEN)
+
+#ifdef __EXPT_CCCI_TTY_IT__
+#define EXPT_TTY_TX_GPD_TYPE    QBM_TYPE_CCCI_COMM
+#define EXPT_TTY_RX_GPD_TYPE    QBM_TYPE_CCCI_COMM
+#else
+#define EXPT_TTY_TX_GPD_TYPE    QBM_TYPE_TTY_INT
+#define EXPT_TTY_RX_GPD_TYPE    QBM_TYPE_TTY_INT
+#endif
+
+#define EXCP_HALT()             while(1)
+
+#ifdef __EXPT_CCCI_TTY_IT__
+static DCL_UINT8 bm_buf_excp_tx[QBM_QUEUE_GET_MEM_SIZE(QBM_TYPE_CCCI_COMM, TX_BUF_NUM)];
+static DCL_UINT8 bm_buf_excp_rx[QBM_QUEUE_GET_MEM_SIZE(QBM_TYPE_CCCI_COMM, RX_BUF_NUM)];
+#else
+static DCL_UINT8 bm_buf_excp_tx[QBM_QUEUE_GET_MEM_SIZE(QBM_SIZE_TTY_INT, TX_BUF_NUM)];
+static DCL_UINT8 bm_buf_excp_rx[QBM_QUEUE_GET_MEM_SIZE(QBM_SIZE_TTY_INT, RX_BUF_NUM)];
+#endif
+
+static void *excp_tgpd_head = NULL;
+static void *excp_tgpd_tail = NULL;
+static void *excp_rgpd_head = NULL;
+static void *excp_rgpd_tail = NULL;
+
+static void *excp_tgpd_free_head = NULL;
+static void *excp_tgpd_free_tail = NULL;
+static void *excp_rgpd_free_head = NULL;
+static void *excp_rgpd_free_tail = NULL;
+
+typedef enum {
+    GPD_TYPE_TX,
+    GPD_TYPE_RX,
+} GPD_TYPE;
+
+
+#define BUSY_LOOP(_n) do{volatile int i; volatile int j=0; for (i=0; i<_n; i++) {j+=i*2;}}while(0)
+
+extern void dbg_print(char *fmt,...);
+
+#define TTYUT_DBG_PRINT(...)
+
+
+/*for debug only (CCCI)*/
+static volatile kal_uint32 DBG_LOCK = 1; 
+
+#define BUSY_STOP()                          \
+    do{                                      \
+        while(1){                            \
+            if(DBG_LOCK == 0) break;         \
+        }                                    \
+    }while(0)                                \
+
+void _excp_qbm_init(void)
+{
+    bm_queue_config conf;
+    kal_uint32 size;
+    kal_uint8 *pool;
+    
+    qbm_init();
+
+    /* Tx GPD queue init */
+    qbm_init_q_config(&conf);
+    size = QBM_QUEUE_GET_MEM_SIZE(EXPT_TTY_TX_GPD_TYPE, TX_BUF_NUM);
+    pool = &bm_buf_excp_tx[0];
+    conf.buff_num = TX_BUF_NUM;
+    conf.p_mem_pool_str = pool;
+    conf.p_mem_pool_end = pool + size;
+    qbm_init_queue_non_free(EXPT_TTY_TX_GPD_TYPE, &conf, &excp_tgpd_head, &excp_tgpd_tail);
+    
+    excp_tgpd_free_head = excp_tgpd_head;
+    excp_tgpd_free_tail = excp_tgpd_tail;
+
+    /* Rx GPD queue init */
+    qbm_init_q_config(&conf);
+    size = QBM_QUEUE_GET_MEM_SIZE(EXPT_TTY_RX_GPD_TYPE, RX_BUF_NUM);
+    pool = &bm_buf_excp_rx[0];
+    conf.buff_num = RX_BUF_NUM;
+    conf.p_mem_pool_str = pool;
+    conf.p_mem_pool_end = pool + size;
+    qbm_init_queue_non_free(EXPT_TTY_RX_GPD_TYPE, &conf, &excp_rgpd_head, &excp_rgpd_tail);
+
+    excp_rgpd_free_head = excp_rgpd_head;
+    excp_rgpd_free_tail = excp_rgpd_tail;
+
+}
+
+/**
+ *  @ return    gpd number allocated successfully
+ */
+static DCL_UINT16 _excp_alloc_gpd(
+        GPD_TYPE type,
+        kal_uint32 buff_num,
+        void **pp_head, 
+        void **pp_tail
+        )
+{
+    kal_uint16 alloc_num = 0;
+    void *free_head;
+    void *free_tail;
+    void *cur;
+    void *pre = NULL;
+
+    free_head = (type == GPD_TYPE_TX) ? excp_tgpd_free_head : excp_rgpd_free_head;
+    free_tail = (type == GPD_TYPE_TX) ? excp_tgpd_free_tail : excp_rgpd_free_tail;
+
+    cur = free_head;
+    
+    while (cur != NULL && buff_num > 0)
+    {
+        alloc_num ++;
+        buff_num --;
+        pre = cur;
+        cur = QBM_DES_GET_NEXT(cur);
+    }
+
+    *pp_head = free_head;
+    *pp_tail = pre;
+
+    if (type == GPD_TYPE_TX) {
+        excp_tgpd_free_head = cur;
+    } else {
+        excp_rgpd_free_head = cur;
+    }
+
+    return alloc_num;
+}
+
+static void _excp_free_gpd(
+        GPD_TYPE type,
+        void *p_head, 
+        void *p_tail
+        )
+{
+    void *free_head;
+    void *free_tail;
+
+    free_head = (type == GPD_TYPE_TX) ? excp_tgpd_free_head : excp_rgpd_free_head;
+    free_tail = (type == GPD_TYPE_TX) ? excp_tgpd_free_tail : excp_rgpd_free_tail;
+
+    if (free_head == NULL) {
+        free_head = p_head;
+    } else {
+        QBM_DES_SET_NEXT(free_tail, p_head);
+    }
+    free_tail = p_tail;
+
+    if (type == GPD_TYPE_TX) {
+        excp_tgpd_free_head = free_head;
+        excp_tgpd_free_tail = free_tail;
+    } else {
+        excp_rgpd_free_head = free_head;
+        excp_rgpd_free_tail = free_tail;
+    }
+}
+
+
+static kal_uint32 _excp_rst_gpd_list(kal_uint32 type,qbm_gpd* first_gpd, qbm_gpd* last_gpd)
+{
+    qbm_gpd*            current_gpd = NULL;
+    qbm_gpd*            next_gpd = NULL;
+    kal_uint32          num_gpd = 0;
+    
+    ASSERT(first_gpd && last_gpd);
+    current_gpd = first_gpd;
+
+    do {
+        next_gpd = QBM_DES_GET_NEXT(current_gpd);
+        qbm_reset_pd(type, (void*)current_gpd);
+        qbm_cal_set_checksum((kal_uint8 *)current_gpd);
+        QBM_CACHE_FLUSH(current_gpd, sizeof(qbm_gpd));
+        num_gpd ++;
+        if ( current_gpd == last_gpd )
+        {
+            break;
+        }        
+        current_gpd = next_gpd;
+    } while ( current_gpd != NULL );
+
+    return num_gpd;
+}
+
+static void* _excp_get_qbm_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 _excp_set_qbm_datalen(void* gpd, kal_uint32 data_len)
+{
+    void* bd = NULL;
+
+    ASSERT(NULL != gpd);
+    /*QBM_TYPE_CCCI_COMM specific function*/
+    ASSERT(QBM_TYPE_CCCI_COMM == QBM_GET_TYPE(gpd));
+    /*Must have BD*/
+    ASSERT(0 != QBM_DES_GET_BDP(gpd));
+
+    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 void excp_loopback_test(DCL_HANDLE handle, kal_bool is_before_reset, kal_uint32 num)
+{
+    unsigned char *tx_buf_ptr;
+    unsigned char *rx_buf_ptr;
+    kal_char trigger_string[50] = {0};
+    kal_uint32 i;
+    kal_uint32 total_rx_num;
+    TTY_CTRL_EXCP_ASSIGN_RX_GPD_T ttyCtlAsnRxGpd;       
+    TTY_CTRL_EXCP_GET_RX_GPD_T ttyCtlGetRxGpd;
+    TTY_CTRL_EXCP_TX_GPD_T ttyCtlTxGpd;
+    TTY_CTRL_EXCP_TX_DONE_INFO_T ttyCtlTxDoneInfo;
+    TTY_CTRL_EXCP_HIF_STATE_T ttyCtlHifSt;
+    UART_CTRL_GET_CHUNK_SIZE_T ur_ctrl_get_chunk_size;
+
+    /*
+        Wait a period of time to let Host have enought time to open com port
+    */
+    for (i = 0; i < 500000; i ++)
+    {
+        if (!is_before_reset) {DclSerialPort_Control(handle, TTY_CMD_EXCEPTION_HIF_POLL, NULL); }
+        BUSY_LOOP(100);
+    }
+
+    /* 
+        Send a packet to trigger Host start loopback test
+        #format: "exception num" (ex. "exception 50")
+    */
+    _excp_alloc_gpd(GPD_TYPE_TX, 1, &ttyCtlTxGpd.first_gpd, &ttyCtlTxGpd.last_gpd);
+    tx_buf_ptr = QBM_DES_GET_DATAPTR(ttyCtlTxGpd.first_gpd);
+    kal_mem_set(trigger_string, 0, sizeof(trigger_string));
+    sprintf(trigger_string, "exception %d", num);
+    kal_mem_cpy(tx_buf_ptr, trigger_string, strlen(trigger_string)+1);
+
+    // Set Tx GPD
+    QBM_CACHE_FLUSH(tx_buf_ptr, strlen(trigger_string)+1);
+    QBM_DES_SET_DATALEN(ttyCtlTxGpd.first_gpd, strlen(trigger_string)+1);
+    QBM_DES_SET_HWO(ttyCtlTxGpd.first_gpd);
+    qbm_cal_set_checksum(ttyCtlTxGpd.first_gpd);
+    QBM_CACHE_FLUSH(ttyCtlTxGpd.first_gpd, sizeof(qbm_gpd));
+    DclSerialPort_Control(handle, TTY_CMD_EXCEPTION_TX_GPD, (DCL_CTRL_DATA_T*) &ttyCtlTxGpd);
+    // Polling Tx Done Info until all Tx GPD are sent and retrieved
+    do {
+        if (!is_before_reset) {DclSerialPort_Control(handle, TTY_CMD_EXCEPTION_HIF_POLL, NULL); }
+        
+        DclSerialPort_Control(handle, TTY_CMD_EXCEPTION_TX_DONE_INFO, (DCL_CTRL_DATA_T*) &ttyCtlTxDoneInfo);
+    
+        if (ttyCtlTxDoneInfo.num > 0) {
+            _excp_free_gpd(GPD_TYPE_TX, ttyCtlTxDoneInfo.first_gpd, ttyCtlTxDoneInfo.last_gpd);
+            break;
+        }
+    } while (1);
+
+    
+    /* Assign Rx GPD to driver */   
+    _excp_alloc_gpd(GPD_TYPE_RX, 2/*1 for tailed GPD*/, &ttyCtlAsnRxGpd.first_gpd, &ttyCtlAsnRxGpd.last_gpd);
+    DclSerialPort_Control(handle, TTY_CMD_GET_CHUNK_SIZE, (DCL_CTRL_DATA_T*)&ur_ctrl_get_chunk_size);
+    // first gpd
+    if(ur_ctrl_get_chunk_size.chunkSize == 1)
+    {
+        QBM_DES_SET_ALLOW_LEN(ttyCtlAsnRxGpd.first_gpd, EXCPT_TTY_UT_CHUNK_SIZE_DEFAULT);
+    }
+    else
+    {
+        QBM_DES_SET_ALLOW_LEN(ttyCtlAsnRxGpd.first_gpd, ur_ctrl_get_chunk_size.chunkSize);
+    }
+    QBM_DES_SET_HWO(ttyCtlAsnRxGpd.first_gpd);
+    qbm_cal_set_checksum(ttyCtlAsnRxGpd.first_gpd);
+    QBM_CACHE_FLUSH(ttyCtlAsnRxGpd.first_gpd, sizeof(qbm_gpd));
+    // last gpd
+    if(ur_ctrl_get_chunk_size.chunkSize == 1)
+    {
+        QBM_DES_SET_ALLOW_LEN(ttyCtlAsnRxGpd.first_gpd, EXCPT_TTY_UT_CHUNK_SIZE_DEFAULT);
+    }
+    else
+    {
+        QBM_DES_SET_ALLOW_LEN(ttyCtlAsnRxGpd.last_gpd, ur_ctrl_get_chunk_size.chunkSize);
+    }
+    QBM_DES_SET_HWO(ttyCtlAsnRxGpd.last_gpd);
+    qbm_cal_set_checksum(ttyCtlAsnRxGpd.last_gpd);
+    QBM_CACHE_FLUSH(ttyCtlAsnRxGpd.last_gpd, sizeof(qbm_gpd));
+    
+    DclSerialPort_Control(handle, TTY_CMD_EXCEPTION_ASSIGN_RX_GPD, (DCL_CTRL_DATA_T*) &ttyCtlAsnRxGpd);
+    
+    total_rx_num = 0;
+    while (total_rx_num < num) // Polling Received Rx GPD and transmit the data to Host
+    {       
+        void *cur_tx;
+        void *cur_rx;
+        kal_uint16 rx_len;
+        kal_uint16 gpd_num;
+        
+        /* Get Rx GPD */
+        do {
+            if (!is_before_reset) {DclSerialPort_Control(handle, TTY_CMD_EXCEPTION_HIF_POLL, NULL);}
+            DclSerialPort_Control(handle, TTY_CMD_EXCEPTION_GET_RX_GPD, (DCL_CTRL_DATA_T*) &ttyCtlGetRxGpd);
+        } while (ttyCtlGetRxGpd.num == 0);
+        total_rx_num += ttyCtlGetRxGpd.num;
+        TTYUT_DBG_PRINT("[EXCEPT TTYUT] receive %d gpds, has received total %d gpds\r\n", ttyCtlGetRxGpd.num, total_rx_num);
+    
+        /* Allocate Tx GPD and re-transmit the rx data to Host */
+        gpd_num = ttyCtlGetRxGpd.num;
+        _excp_alloc_gpd(GPD_TYPE_TX, gpd_num, &ttyCtlTxGpd.first_gpd, &ttyCtlTxGpd.last_gpd);
+    
+        cur_rx = ttyCtlGetRxGpd.first_gpd;
+        cur_tx = ttyCtlTxGpd.first_gpd;
+        
+        for (i = 0; i < ttyCtlGetRxGpd.num; i ++)
+        {
+            rx_buf_ptr = QBM_DES_GET_DATAPTR(cur_rx);
+            rx_len = QBM_DES_GET_DATALEN(cur_rx);
+            tx_buf_ptr = QBM_DES_GET_DATAPTR(cur_tx);
+    
+            QBM_CACHE_INVALID(rx_buf_ptr, rx_len);
+            kal_mem_cpy(tx_buf_ptr, rx_buf_ptr, rx_len);
+            QBM_CACHE_FLUSH(tx_buf_ptr, rx_len);
+    
+            /* Set Tx GPD */
+            QBM_DES_SET_DATALEN(cur_tx, rx_len);
+            QBM_DES_SET_HWO(cur_tx);
+            qbm_cal_set_checksum(cur_tx);
+            QBM_CACHE_FLUSH(cur_tx, sizeof(qbm_gpd));
+    
+            /* Reset Rx GPD */
+            QBM_DES_SET_ALLOW_LEN(cur_rx, ur_ctrl_get_chunk_size.chunkSize);
+            QBM_DES_SET_HWO(cur_rx);
+            qbm_cal_set_checksum(cur_rx);
+            QBM_CACHE_FLUSH(cur_rx, sizeof(qbm_gpd));               
+    
+            cur_tx = QBM_DES_GET_NEXT(cur_tx);
+            cur_rx = QBM_DES_GET_NEXT(cur_rx);
+        }
+        DclSerialPort_Control(handle, TTY_CMD_EXCEPTION_TX_GPD, (DCL_CTRL_DATA_T*) &ttyCtlTxGpd);
+
+        if (!is_before_reset) {DclSerialPort_Control(handle, TTY_CMD_EXCEPTION_HIF_POLL, NULL); }
+        
+        /* Re-assign Rx GPD to driver */
+        ttyCtlAsnRxGpd.first_gpd = ttyCtlGetRxGpd.first_gpd;
+        ttyCtlAsnRxGpd.last_gpd = ttyCtlGetRxGpd.last_gpd;
+        DclSerialPort_Control(handle, TTY_CMD_EXCEPTION_ASSIGN_RX_GPD, (DCL_CTRL_DATA_T*) &ttyCtlAsnRxGpd);
+    
+        /* Polling Tx Done Info until all Tx GPD are sent and retrieved */
+        do {
+            if (!is_before_reset) {DclSerialPort_Control(handle, TTY_CMD_EXCEPTION_HIF_POLL, NULL);}
+            DclSerialPort_Control(handle, TTY_CMD_EXCEPTION_TX_DONE_INFO, (DCL_CTRL_DATA_T*) &ttyCtlTxDoneInfo);
+    
+            if (ttyCtlTxDoneInfo.num > 0) {
+                _excp_free_gpd(GPD_TYPE_TX, ttyCtlTxDoneInfo.first_gpd, ttyCtlTxDoneInfo.last_gpd);
+                gpd_num -= ttyCtlTxDoneInfo.num;
+                TTYUT_DBG_PRINT("[EXCEPT TTYUT] has sent %d gpds\r\n", ttyCtlTxDoneInfo.num);
+            }
+        } while (gpd_num > 0);
+    
+        /* Check HIF state */
+        DclSerialPort_Control(handle, TTY_CMD_EXCEPTION_HIF_STATE, (DCL_CTRL_DATA_T*) &ttyCtlHifSt);
+        if (ttyCtlHifSt.hif_state != HIF_STATE_NORMAL) {
+            EXCP_HALT();
+        }
+
+        if (!is_before_reset) {DclSerialPort_Control(handle, TTY_CMD_EXCEPTION_HIF_POLL, NULL); }
+    }   
+
+}
+
+static void excp_ccci_loopback_test(DCL_HANDLE handle, kal_uint32 num)
+{
+    unsigned char *tx_buf_ptr;
+    unsigned char *rx_buf_ptr;
+    kal_char trigger_string[50] = {0};
+    kal_uint32 i;
+    kal_uint32 total_rx_num;
+    TTY_CTRL_EXCP_ASSIGN_RX_GPD_T ttyCtlAsnRxGpd;       
+    TTY_CTRL_EXCP_GET_RX_GPD_T ttyCtlGetRxGpd;
+    TTY_CTRL_EXCP_TX_GPD_T ttyCtlTxGpd;
+    TTY_CTRL_EXCP_TX_DONE_INFO_T ttyCtlTxDoneInfo;
+    TTY_CTRL_EXCP_HIF_STATE_T ttyCtlHifSt;
+    UART_CTRL_GET_MTU_SIZE_T ur_ctrl_get_mtu_size;
+    kal_uint32 tmp_num;
+
+    /*For debug test only*/
+    //BUSY_STOP();
+    
+    /* Assign Rx GPD to driver */
+    // TODO:Need to revise APIs. Because in exception mode(espicailly in HISR), some QBM APIs shall not be used. (ex:enhance mutex)
+    //tmp_num = _excp_alloc_gpd(GPD_TYPE_RX, 2/*1 for tailed GPD*/, &ttyCtlAsnRxGpd.first_gpd, &ttyCtlAsnRxGpd.last_gpd);
+    tmp_num = qbmt_alloc_q_no_tail(EXPT_TTY_RX_GPD_TYPE, 2, &ttyCtlAsnRxGpd.first_gpd, &ttyCtlAsnRxGpd.last_gpd);
+    if(tmp_num!= 2) while(1);
+    DclSerialPort_Control(handle, TTY_CMD_GET_MTU_SIZE, (DCL_CTRL_DATA_T*)&ur_ctrl_get_mtu_size);
+    QBM_DES_SET_ALLOW_LEN(ttyCtlAsnRxGpd.first_gpd, ur_ctrl_get_mtu_size.ulmtu_sz);
+    QBM_DES_SET_HWO(ttyCtlAsnRxGpd.first_gpd);
+    qbm_cal_set_checksum(ttyCtlAsnRxGpd.first_gpd);
+    QBM_CACHE_FLUSH(ttyCtlAsnRxGpd.first_gpd, sizeof(qbm_gpd));
+    // last gpd
+    QBM_DES_SET_ALLOW_LEN(ttyCtlAsnRxGpd.last_gpd, ur_ctrl_get_mtu_size.ulmtu_sz);
+    QBM_DES_SET_HWO(ttyCtlAsnRxGpd.last_gpd);
+    qbm_cal_set_checksum(ttyCtlAsnRxGpd.last_gpd);
+    QBM_CACHE_FLUSH(ttyCtlAsnRxGpd.last_gpd, sizeof(qbm_gpd));
+    
+    DclSerialPort_Control(handle, TTY_CMD_EXCEPTION_ASSIGN_RX_GPD, (DCL_CTRL_DATA_T*) &ttyCtlAsnRxGpd);
+    
+    total_rx_num = 0;
+    //while (total_rx_num < num) // Polling Received Rx GPD and transmit the data to Host
+    while(1)
+    {       
+        void *cur_tx;
+        void *cur_rx;
+        kal_uint16 rx_len;
+        kal_uint16 gpd_num;
+        
+        /* Get Rx GPD */
+        do {
+            DclSerialPort_Control(handle, TTY_CMD_EXCEPTION_HIF_POLL, NULL);
+            DclSerialPort_Control(handle, TTY_CMD_EXCEPTION_GET_RX_GPD, (DCL_CTRL_DATA_T*) &ttyCtlGetRxGpd);
+        } while (ttyCtlGetRxGpd.num == 0);
+        total_rx_num += ttyCtlGetRxGpd.num;
+        TTYUT_DBG_PRINT("[EXCEPT TTYUT] receive %d gpds, has received total %d gpds\r\n", ttyCtlGetRxGpd.num, total_rx_num);
+    
+        /* Allocate Tx GPD and re-transmit the rx data to Host */
+        gpd_num = ttyCtlGetRxGpd.num;
+        //_excp_alloc_gpd(GPD_TYPE_TX, gpd_num, &ttyCtlTxGpd.first_gpd, &ttyCtlTxGpd.last_gpd);
+        tmp_num = qbmt_alloc_q_no_tail(EXPT_TTY_TX_GPD_TYPE, gpd_num, &ttyCtlTxGpd.first_gpd, &ttyCtlTxGpd.last_gpd);
+        if(tmp_num!= gpd_num) while(1);
+
+        cur_rx = ttyCtlGetRxGpd.first_gpd;
+        cur_tx = ttyCtlTxGpd.first_gpd;
+        
+        for (i = 0; i < ttyCtlGetRxGpd.num; i ++)
+        {
+            rx_buf_ptr = _excp_get_qbm_dataptr(cur_rx);
+            rx_len = QBM_DES_GET_DATALEN(cur_rx);
+            tx_buf_ptr = _excp_get_qbm_dataptr(cur_tx);
+    
+            QBM_CACHE_INVALID(rx_buf_ptr, rx_len);
+            kal_mem_cpy(tx_buf_ptr, rx_buf_ptr, rx_len);
+            QBM_CACHE_FLUSH(tx_buf_ptr, rx_len);
+    
+            /* Set Tx GPD */
+            _excp_set_qbm_datalen(cur_tx, rx_len);
+            QBM_DES_SET_HWO(cur_tx);
+            qbm_cal_set_checksum(cur_tx);
+            QBM_CACHE_FLUSH(cur_tx, sizeof(qbm_gpd));
+            
+            /* Reset Rx GPD */
+            _excp_rst_gpd_list(EXPT_TTY_RX_GPD_TYPE,cur_rx,cur_rx);
+            QBM_DES_SET_ALLOW_LEN(cur_rx, ur_ctrl_get_mtu_size.ulmtu_sz);
+            //QBM_DES_SET_HWO(cur_rx);
+            qbm_cal_set_checksum(cur_rx);
+            QBM_CACHE_FLUSH(cur_rx, sizeof(qbm_gpd));               
+    
+            cur_tx = QBM_DES_GET_NEXT(cur_tx);
+            cur_rx = QBM_DES_GET_NEXT(cur_rx);
+        }
+        DclSerialPort_Control(handle, TTY_CMD_EXCEPTION_TX_GPD, (DCL_CTRL_DATA_T*) &ttyCtlTxGpd);
+
+        DclSerialPort_Control(handle, TTY_CMD_EXCEPTION_HIF_POLL, NULL);
+        
+        /*Re-assign Rx GPD to driver */
+        ttyCtlAsnRxGpd.first_gpd = ttyCtlGetRxGpd.first_gpd;
+        ttyCtlAsnRxGpd.last_gpd = ttyCtlGetRxGpd.last_gpd;
+        DclSerialPort_Control(handle, TTY_CMD_EXCEPTION_ASSIGN_RX_GPD, (DCL_CTRL_DATA_T*) &ttyCtlAsnRxGpd);
+    
+        /* Polling Tx Done Info until all Tx GPD are sent and retrieved */
+        do {
+            DclSerialPort_Control(handle, TTY_CMD_EXCEPTION_HIF_POLL, NULL);
+
+            /*Debug only to check sdio interrupt status*/
+            //if((*SDIO_IRQ_DL_FTE0SR) & SDIO_INT_MASK) while(1);
+            
+            DclSerialPort_Control(handle, TTY_CMD_EXCEPTION_TX_DONE_INFO, (DCL_CTRL_DATA_T*) &ttyCtlTxDoneInfo);
+    
+            if (ttyCtlTxDoneInfo.num > 0) {
+                //_excp_free_gpd(GPD_TYPE_TX, ttyCtlTxDoneInfo.first_gpd, ttyCtlTxDoneInfo.last_gpd);
+                qbmt_dest_q(ttyCtlTxDoneInfo.first_gpd, ttyCtlTxDoneInfo.last_gpd);
+                gpd_num -= ttyCtlTxDoneInfo.num;
+                TTYUT_DBG_PRINT("[EXCEPT TTYUT] has sent %d gpds\r\n", ttyCtlTxDoneInfo.num);
+            }
+        } while (gpd_num > 0);
+    
+        /* Check HIF state */
+        DclSerialPort_Control(handle, TTY_CMD_EXCEPTION_HIF_STATE, (DCL_CTRL_DATA_T*) &ttyCtlHifSt);
+        if (ttyCtlHifSt.hif_state != HIF_STATE_NORMAL) {
+            EXCP_HALT();
+        }
+
+        DclSerialPort_Control(handle, TTY_CMD_EXCEPTION_HIF_POLL, NULL);
+    }   
+
+}
+
+DCL_STATUS excp_ttyut(void)
+{
+    DCL_HANDLE handle;
+
+    //for debug only
+    //BUSY_STOP();
+    
+    hmu_except_init();
+
+    TTYUT_DBG_PRINT("[EXCEPT TTYUT] excp_ttyut start\r\n");
+
+    handle = DclSerialPort_Open(EXCEPTION_TEST_PORT, 0);
+
+    /* Init QBM for exception */
+    _excp_qbm_init();
+
+    /* Test Case 1: Loopback before RESET */
+        /* HIF init and Clear channel */
+    DclSerialPort_Control(handle, TTY_CMD_EXCEPTION_HIF_INIT, NULL);
+    DclSerialPort_Control(handle, TTY_CMD_EXCEPTION_CLEAR_CHANNEL, NULL);
+
+#ifdef __EXPT_CCCI_TTY_IT__
+    excp_ccci_loopback_test(handle, TEST_LB_PKT_NUM);
+#else
+    //BUSY_LOOP(60000000);
+    TTYUT_DBG_PRINT("[EXCEPT TTYUT] excp_ttyut case 1\r\n");
+    {
+        excp_loopback_test(handle, KAL_TRUE, TEST_LB_PKT_NUM);
+    }
+
+    /* Test Case 2: RESET */
+    TTYUT_DBG_PRINT("[EXCEPT TTYUT] excp_ttyut case 2\r\n");
+    {
+        DclSerialPort_Control(handle, TTY_CMD_EXCEPTION_RESET, NULL);
+    }
+
+    /* Test Case 3: Loopback after RESET */
+        /* HIF init */
+    DclSerialPort_Control(handle, TTY_CMD_EXCEPTION_HIF_INIT, NULL);
+    //BUSY_LOOP(60000000);
+    TTYUT_DBG_PRINT("[EXCEPT TTYUT] excp_ttyut case 3\r\n");
+    {
+        excp_loopback_test(handle, KAL_FALSE, TEST_LB_PKT_NUM);
+    }
+
+    /* Test Case 4: HIF_STATE return TXERROR */
+    TTYUT_DBG_PRINT("[EXCEPT TTYUT] excp_ttyut case 4\r\n");
+    {
+        TTY_CTRL_EXCP_TX_GPD_T ttyCtlTxGpd;
+        TTY_CTRL_EXCP_TX_DONE_INFO_T ttyCtlTxDoneInfo;
+        TTY_CTRL_EXCP_HIF_STATE_T ttyCtlHifSt;
+        kal_uint16 gpd_num;
+        kal_uint16 count;
+
+        BUSY_LOOP(50000);
+        while (1)
+        {
+            gpd_num = _excp_alloc_gpd(GPD_TYPE_TX, 1, &ttyCtlTxGpd.first_gpd, &ttyCtlTxGpd.last_gpd);
+            TTYUT_DBG_PRINT("[EXCEPT TTYUT] allocate %d gpd\r\n", gpd_num);
+            if (gpd_num == 0) {
+                break;
+            }
+            QBM_DES_SET_DATALEN(ttyCtlTxGpd.first_gpd, 100);
+            QBM_DES_SET_HWO(ttyCtlTxGpd.first_gpd);
+            qbm_cal_set_checksum(ttyCtlTxGpd.first_gpd);
+            QBM_CACHE_FLUSH(ttyCtlTxGpd.first_gpd, sizeof(qbm_gpd));
+
+            BUSY_LOOP(300000);
+            DclSerialPort_Control(handle, TTY_CMD_EXCEPTION_TX_GPD, (DCL_CTRL_DATA_T*) &ttyCtlTxGpd);
+            DclSerialPort_Control(handle, TTY_CMD_EXCEPTION_HIF_POLL, NULL);
+        }
+
+        count = 10000;
+        while (count-- > 0)
+        {
+            BUSY_LOOP(30000);
+            DclSerialPort_Control(handle, TTY_CMD_EXCEPTION_TX_DONE_INFO, (DCL_CTRL_DATA_T*) &ttyCtlTxDoneInfo);
+        }
+        
+        DclSerialPort_Control(handle, TTY_CMD_EXCEPTION_HIF_STATE, (DCL_CTRL_DATA_T*) &ttyCtlHifSt);
+        if (ttyCtlHifSt.hif_state != HIF_STATE_TXERROR) {
+            TTYUT_DBG_PRINT("[EXCEPT TTYUT] ERROR!! HIF_STATE return NORMAL\r\n");
+            EXCP_HALT();
+        } else {
+            TTYUT_DBG_PRINT("[EXCEPT TTYUT] HIF_STATE return HIF_STATE_TXERROR\r\n");
+        }
+    }
+
+    TTYUT_DBG_PRINT("[EXCEPT TTYUT] excp_ttyut end\r\n");
+#endif
+    return STATUS_OK;
+}
+
+static kal_bool excp_ttyut_task_init(void)
+{
+    return KAL_TRUE;
+}
+
+static void excp_ttyut_task_main(task_entry_struct *task_entry_ptr)
+{
+    DCL_HANDLE handle;
+    UART_CTRL_PUT_BYTES_T ur_ctrl_putbytes;
+    char *dummy_string = "DUMMYdummyDummY";
+    DCL_STATUS status;
+    UART_CTRL_GET_DRV_STATE_T getDrvState;
+
+    handle = DclSerialPort_Open(EXCEPTION_TEST_PORT, 0);
+
+    DclSerialPort_UpModuleInit(handle, MOD_EXCP_TTYUT, 0); // conventional init
+
+    /*If taking CCCI exception IT test, task will be blocked here. Because, driver is attached when exception init*/
+    getDrvState.u4OwnerId = MOD_EXCP_TTYUT;
+    do {
+        kal_sleep_task(KAL_TICKS_100_MSEC);
+        status = DclSerialPort_Control(handle, TTY_CMD_GET_DRV_STATE, (DCL_CTRL_DATA_T*) &getDrvState);
+    } while ((getDrvState.drv_state != DRV_ST_ATTACHED) || (status != STATUS_OK)); 
+
+    kal_sleep_task(KAL_TICKS_5_SEC);
+
+    /* Transmit a dummy packet */
+    ur_ctrl_putbytes.u4OwenrId = MOD_EXCP_TTYUT;
+    ur_ctrl_putbytes.puBuffaddr = (DCL_UINT8*)dummy_string;
+    ur_ctrl_putbytes.u2Length = strlen(dummy_string);
+    DclSerialPort_Control(handle, SIO_CMD_PUT_BYTES, (DCL_CTRL_DATA_T*) &ur_ctrl_putbytes);
+
+    kal_sleep_task(KAL_TICKS_5_SEC);
+
+    /* Trigger an assert to enter exception mode */
+    ASSERT(0);
+}
+
+kal_bool excp_ttyut_create(comptask_handler_struct **handle)
+{
+    static const comptask_handler_struct excp_ttyut_handler_info =
+    {
+        excp_ttyut_task_main,        /* task entry function */
+        excp_ttyut_task_init,        /* task initialization function */
+        NULL        /* task reset handler */
+    };
+
+    TTYUT_DBG_PRINT("=========>excp_ttyut_create\r\n");
+
+    *handle = (comptask_handler_struct *)&excp_ttyut_handler_info;
+    return KAL_TRUE;
+}
+
diff --git a/mcu/driver/tty/src/tty_unit_test.c b/mcu/driver/tty/src/tty_unit_test.c
new file mode 100644
index 0000000..099ec7c
--- /dev/null
+++ b/mcu/driver/tty/src/tty_unit_test.c
@@ -0,0 +1,3302 @@
+#include "kal_public_api.h"
+#include "syscomp_config.h"
+#include "task_config.h"
+#include "sys_test.h"
+#include "dcl.h"
+#include "qmu_bm_util.h"
+#include "drv_msgid.h"
+
+#if !defined ATEST_SYS_TTYCORE
+#error "This file is used for system test only."
+#endif
+
+/***************************************************************************
+                Macro Declaration
+ ***************************************************************************/
+#define ST_MOD_NAME		"TTYUT"
+
+#define MOD_TTY_UT		MOD_SYS_TEST
+#define DRV_TTY_UT		MOD_SYS_TEST
+#define MOD_CURRENT		kal_get_active_module_id()
+
+#define UART_DEV_CNT	(uart_max_port - uart_port1 + 1)
+
+#define HW_BUFF_SIZE	8192
+#define UT_TEST_SIZE	8000
+#define UT_CHUNK_SIZE	512
+#define UT_DATA_MASK	0x000000CC
+
+#define DCL_UART_MAGIC_NUM 0x40000000
+
+#define DCL_UART_GET_DEV(_handle) ((DCL_DEV)((_handle) & (~DCL_UART_MAGIC_NUM)))
+
+#define FAIL_MSG(fmt, ...)	do { \
+								kal_sprintf(p_ret_err_str, "%s():%s:%d " fmt, __FUNCTION__, __FILE__, __LINE__, ##__VA_ARGS__); \
+								*p_ret_err_str_sz = strlen(p_ret_err_str); \
+							} while (0)
+#define FAIL_MSG_EXT(ext, fmt, ...)	do { \
+										kal_sprintf(p_ret_err_str, strcat(ext, "%s():%s:%d " fmt), __FUNCTION__, __FILE__, __LINE__, ##__VA_ARGS__); \
+										*p_ret_err_str_sz = strlen(p_ret_err_str); \
+									} while (0)
+#define MIN(_x, _y) (((_x) > (_y)) ? (_y) : (_x))
+
+#define list_each_gpd_no_tail(_gpd, _first_gpd, _last_gpd) \
+												for ( _gpd = _first_gpd; _gpd != _last_gpd; _gpd = QBM_DES_GET_NEXT(_gpd)) 
+
+#define list_each_gpd(_gpd, _first_gpd, _last_gpd) QBM_DES_SET_NEXT(_last_gpd, NULL); \
+												for ( _gpd = _first_gpd; _gpd != NULL; _gpd = QBM_DES_GET_NEXT(_gpd)) 
+#define list_each_bd(_bd, _first_bd) for (_bd = _first_bd; _bd != NULL; _bd = QBM_DES_GET_NEXT(_bd))
+
+/***************************************************************************
+                Data Structure
+ ***************************************************************************/
+// This flag used to check event occur, and it will be "extern" in dcl_tty.c
+kal_bool ut_assert_flag = KAL_FALSE;
+
+typedef struct _UtInstance {
+/***********************
+	Upper Module
+ ***********************/
+	// For Receiving Ior From RxCb (New Rx Path)
+	tty_io_request_t *Rx_Ior;
+ 
+/***********************
+	Driver
+ ***********************/
+	// RxGpdQue
+	void *Rx_first_gpd;
+	void *Rx_last_gpd;
+	// TxGpdQue
+	void *Tx_first_gpd;
+	void *Tx_last_gpd;
+	// Flag
+	kal_bool Need_Tx_done_cb;	
+	
+/***********************
+	Hardware buffer
+ ***********************/
+	int size;
+	int start;
+	char HwBuff[HW_BUFF_SIZE];
+} UtInstance;
+
+static UtInstance Dev_Mgmt[UART_DEV_CNT];
+
+/***************************************************************************
+                Hardware Buffer Function
+ ***************************************************************************/
+/*
+ * Here is a simple hw buffer
+ * There is no check for data overflow.
+ */
+int Hw_GetRemainSpace(DCL_DEV dev)
+{
+	return HW_BUFF_SIZE - (Dev_Mgmt[dev].start + Dev_Mgmt[dev].size);
+}
+
+void Hw_PushData(DCL_DEV dev, const void *src, kal_uint32 size)
+{
+	char *hwbuff_data_end = Dev_Mgmt[dev].HwBuff + Dev_Mgmt[dev].start + Dev_Mgmt[dev].size;
+	kal_mem_cpy(hwbuff_data_end, src, size);
+	Dev_Mgmt[dev].size += size;
+}
+
+void Hw_PushDataFromTxQue(DCL_DEV dev)
+{
+	void *gpd_t;
+	void *bd_t;
+	
+	list_each_gpd(gpd_t, Dev_Mgmt[dev].Tx_first_gpd, Dev_Mgmt[dev].Tx_last_gpd) {
+		// only push data of gpd with hwo equal to 1
+		if (QBM_DES_GET_HWO(gpd_t)) {
+			if (QBM_DES_GET_BDP(gpd_t)) {
+				list_each_bd(bd_t, QBM_DES_GET_DATAPTR(gpd_t)) {
+					Hw_PushData(dev, QBM_DES_GET_DATAPTR(bd_t), QBM_DES_GET_DATALEN(bd_t));
+				}
+			} else {
+				Hw_PushData(dev, QBM_DES_GET_DATAPTR(gpd_t), QBM_DES_GET_DATALEN(gpd_t));
+			}
+		}
+		
+		// set hwo to 0
+		QBM_DES_CLR_HWO(gpd_t);
+	}
+}
+
+void Hw_PopData(DCL_DEV dev, void *dest, kal_uint32 size)
+{
+	char *hwbuff_data_start = Dev_Mgmt[dev].HwBuff + Dev_Mgmt[dev].start;
+	kal_mem_cpy(dest, hwbuff_data_start, size);
+	Dev_Mgmt[dev].start += size;
+	Dev_Mgmt[dev].size -= size;
+}
+
+void Hw_PopDataToRxQue(DCL_DEV dev)
+{
+	void *gpd_t;
+	void *bd_t;
+	
+	list_each_gpd_no_tail(gpd_t, Dev_Mgmt[dev].Rx_first_gpd, Dev_Mgmt[dev].Rx_last_gpd) {
+		// check hardware buffer still have data
+		if (Dev_Mgmt[dev].size == 0)
+			break;
+	
+		if (QBM_DES_GET_BDP(gpd_t)) {
+			list_each_bd(bd_t, QBM_DES_GET_DATAPTR(gpd_t)) {
+				kal_uint32 len = MIN(QBM_DES_GET_ALLOW_LEN(bd_t), Dev_Mgmt[dev].size);
+				if (len) {
+					Hw_PopData(dev, QBM_DES_GET_DATAPTR(bd_t), len);
+				}
+				QBM_DES_SET_DATALEN(bd_t, len);
+			}
+		} else {
+			kal_uint32 len = MIN(QBM_DES_GET_ALLOW_LEN(gpd_t), Dev_Mgmt[dev].size);
+			if (len) {
+				Hw_PopData(dev, QBM_DES_GET_DATAPTR(gpd_t), len);
+			}
+			QBM_DES_SET_DATALEN(gpd_t, len);
+		}
+		
+		// set hwo to 0
+		QBM_DES_CLR_HWO(gpd_t);
+	}
+}
+
+void Hw_ClearBuff(DCL_DEV dev)
+{
+	kal_mem_set(Dev_Mgmt[dev].HwBuff, 0, HW_BUFF_SIZE);
+
+	Dev_Mgmt[dev].start = 0;
+	Dev_Mgmt[dev].size = 0;
+}
+
+/***************************************************************************
+                Tx/Rx Operator Function
+ ***************************************************************************/
+void Rx_EnQue(DCL_DEV dev, void *_ior)
+{
+	void *gpd_t;
+	tty_io_request_t *ior = (tty_io_request_t *)_ior;
+	
+	// Set gpd HWO to 1,only tail gpd HWO to 0. And then En-Q
+	list_each_gpd(gpd_t, ior->first_gpd, ior->last_gpd) {
+		QBM_DES_SET_HWO(gpd_t);
+	}
+	QBM_DES_CLR_HWO(ior->last_gpd);
+	
+	if (!Dev_Mgmt[dev].Rx_first_gpd) {
+		Dev_Mgmt[dev].Rx_first_gpd = ior->first_gpd;
+		Dev_Mgmt[dev].Rx_last_gpd = ior->last_gpd;
+	} else {
+		qbmt_common_en_q_rx(
+			ior->first_gpd,
+			ior->last_gpd,
+			&Dev_Mgmt[dev].Rx_first_gpd,
+			&Dev_Mgmt[dev].Rx_last_gpd);
+	}
+}
+
+void Tx_EnQue(DCL_DEV dev, void *_ior)
+{
+	void *gpd_t;
+	tty_io_request_t *ior = (tty_io_request_t *)_ior;
+		
+	// Set gpd HWO to 1, And then En-Q
+	list_each_gpd(gpd_t, ior->first_gpd, ior->last_gpd) {
+		QBM_DES_SET_HWO(gpd_t);
+	}
+	
+	if (!Dev_Mgmt[dev].Tx_first_gpd) {
+		Dev_Mgmt[dev].Tx_first_gpd = ior->first_gpd;
+		Dev_Mgmt[dev].Tx_last_gpd = ior->last_gpd;
+	} else {
+		QBM_DES_SET_NEXT(Dev_Mgmt[dev].Tx_last_gpd, ior->first_gpd);
+	}	
+}
+
+void * Rx_DeQueToIor(DCL_DEV dev)
+{
+	void *ior = NULL;
+	void *new_head;
+	void *new_tail;
+	
+	if (Dev_Mgmt[dev].Rx_first_gpd) {
+		qbmt_de_q(
+			&Dev_Mgmt[dev].Rx_first_gpd,
+			&Dev_Mgmt[dev].Rx_last_gpd,
+			&new_head,
+			&new_tail);
+	
+		if (new_head) {
+			ior = QBM_DES_GET_SW_CTRL_FIELD(new_head);
+			((tty_io_request_t *)ior)->first_gpd = new_head;
+			((tty_io_request_t *)ior)->last_gpd = new_tail;
+		}
+	}
+	
+	return ior;
+}
+
+void Rx_Flush_Gpd(DCL_DEV dev)
+{
+	void *Rx_Ior;
+	DCL_HANDLE handle;
+		
+	handle = DclSerialPort_Open(dev, 0);
+
+	// Using RxCb to return the all GPD of Rx Queue 
+	if (Dev_Mgmt[dev].Rx_first_gpd) {
+		Rx_Ior = QBM_DES_GET_SW_CTRL_FIELD(Dev_Mgmt[dev].Rx_first_gpd);
+		((tty_io_request_t *)Rx_Ior)->first_gpd = Dev_Mgmt[dev].Rx_first_gpd;
+		((tty_io_request_t *)Rx_Ior)->last_gpd = Dev_Mgmt[dev].Rx_last_gpd;
+		
+		DclSerialPort_DrvRx(handle, DRV_TTY_UT, Rx_Ior);
+		
+		Dev_Mgmt[dev].Rx_first_gpd = 0;
+		Dev_Mgmt[dev].Rx_last_gpd = 0;
+	}
+}
+
+/*
+ * This function maybe need to be called after Hw_PushDataFromTxQue() invoked.
+ * Because it will flush each gpd without care about whether hwo is set.
+ *
+ * The Hw_PushDataFromTxQue() will be invoked in driver callback with command "TTY_CMD_PUT_BYTES_IOR"
+ */
+void Tx_Flush_Gpd(DCL_DEV dev)
+{
+	void * Tx_Ior;
+	DCL_HANDLE handle;
+				
+	handle = DclSerialPort_Open(dev, 0);
+	
+	// Using TxDoneCb to return Tx GPD or Free gpds
+	if (Dev_Mgmt[dev].Tx_first_gpd) {
+		Tx_Ior = QBM_DES_GET_SW_CTRL_FIELD(Dev_Mgmt[dev].Tx_first_gpd);
+		((tty_io_request_t *)Tx_Ior)->first_gpd = Dev_Mgmt[dev].Tx_first_gpd;
+		((tty_io_request_t *)Tx_Ior)->last_gpd = Dev_Mgmt[dev].Tx_last_gpd;
+		
+		if (Dev_Mgmt[dev].Need_Tx_done_cb) {
+			DclSerialPort_DrvTxDone(handle, DRV_TTY_UT, Tx_Ior);
+		} else {
+			qbmt_dest_q(Dev_Mgmt[dev].Tx_first_gpd, Dev_Mgmt[dev].Tx_last_gpd);
+		}
+		
+		Dev_Mgmt[dev].Tx_first_gpd = 0;
+		Dev_Mgmt[dev].Tx_last_gpd = 0;
+	}
+}
+/***************************************************************************
+                Callback Test Function
+ ***************************************************************************/
+DCL_STATUS 
+_drv_handler_cb(
+	DCL_DEV dev,
+	DCL_CTRL_CMD cmd,
+	DCL_CTRL_DATA_T *data)
+{
+	DCL_STATUS ret_status = STATUS_OK;
+    
+    switch (cmd)
+    {
+        case SIO_CMD_INIT:
+        case SIO_CMD_OPEN:
+		{
+			ret_status = STATUS_OK;
+		}
+            break;        
+			
+        case SIO_CMD_CLOSE:
+        {
+            UART_CTRL_CLOSE_T *prCtrlClose;
+            prCtrlClose = &(data->rUARTCtrlCLOSE);
+			
+			// Flush Tx/Rx GPD (In buffer mode, Flush will do nothing because queue is empty
+			Tx_Flush_Gpd(dev);
+			Rx_Flush_Gpd(dev);
+			
+			// Clear Need_Tx_done_cb flag
+			Dev_Mgmt[dev].Need_Tx_done_cb = KAL_FALSE;
+        }
+            break;
+		
+		case SIO_CMD_PUT_BYTES:
+		{	// Only for Buffer Mode
+			int size;
+			UART_CTRL_PUT_BYTES_T *prCtrlPutBytes;
+			
+			prCtrlPutBytes = &(data->rUARTCtrlPUTBYTES);
+			size = MIN(prCtrlPutBytes->u2Length, UT_CHUNK_SIZE);
+			
+			Hw_PushData(dev, prCtrlPutBytes->puBuffaddr, size);
+			prCtrlPutBytes->u2RetSize = size;
+		}
+			break;
+			
+		case SIO_CMD_GET_BYTES:
+		{	// Only for Buffer Mode
+			int size;
+			UART_CTRL_GET_BYTES_T *prCtrlGetBytes;
+			
+			prCtrlGetBytes = &(data->rUARTCtrlGETBYTES);
+			size = MIN(prCtrlGetBytes->u2Length, UT_CHUNK_SIZE);
+			
+			Hw_PopData(dev, prCtrlGetBytes->puBuffaddr, size);
+			prCtrlGetBytes->u2RetSize = size;
+		}
+			break;
+			
+        case TTY_CMD_NEED_TX_DONE_CB:
+        {
+            UART_CTRL_NEED_TX_DONE_CB_T *prCtrlNeedTxDoneCb;
+            prCtrlNeedTxDoneCb = &(data->rUARTCtrlNeedTxDoneCb);
+			
+			Dev_Mgmt[dev].Need_Tx_done_cb = prCtrlNeedTxDoneCb->needTxDoneCb;
+        }
+            break;
+
+        case TTY_CMD_ASSIGN_RX_IOR:
+        {
+            UART_CTRL_ASSIGN_RX_IOR_T *prCtrlAssignRxIor;
+			
+            prCtrlAssignRxIor = &(data->rUARTCtrlAssignRxIor);
+			
+			// En-Q Rx_Ior
+			Rx_EnQue(dev, prCtrlAssignRxIor->ior);
+        }
+            break;
+        
+        case TTY_CMD_PUT_BYTES_IOR:
+		case TTY_CMD_PUT_BYTES_IOR_LIGHT:
+        {
+			UART_CTRL_PUT_BYTES_IOR_T *prCtrlPutBytesIor;
+			
+            prCtrlPutBytesIor = &(data->rUARTCtrlPUTBYTESIOR);
+		
+			// En-Q Tx_Ior
+			Tx_EnQue(dev, prCtrlPutBytesIor->putIor);
+			
+			// Copy GPD data to HwBuff
+			Hw_PushDataFromTxQue(dev);
+				
+        }
+            break;
+
+        case TTY_CMD_GET_CHUNK_SIZE:
+        {
+            UART_CTRL_GET_CHUNK_SIZE_T *prCtrlChunkSize;
+            prCtrlChunkSize = &(data->rUARTCtrlGETCHUNKSIZE);
+            prCtrlChunkSize->chunkSize = UT_CHUNK_SIZE;
+        }
+            break;
+		case SIO_CMD_SET_OWNER:
+		{
+			// Flush Tx/Rx GPD
+			Tx_Flush_Gpd(dev);
+			Rx_Flush_Gpd(dev);
+			
+			// Clear Need_Tx_done_cb flag
+			Dev_Mgmt[dev].Need_Tx_done_cb = KAL_FALSE;
+		}
+			break;
+			
+        case SIO_CMD_GET_OWNER_ID:
+            break;
+
+        case SIO_CMD_CLR_RX_BUF:
+		{
+			Rx_Flush_Gpd(dev);
+        }
+            break;
+        
+        case SIO_CMD_CLR_TX_BUF:
+        {
+			Tx_Flush_Gpd(dev);
+        }
+            break;
+		
+		case SIO_CMD_GET_TX_AVAIL:
+		{	// Only for Buffer Mode
+			UART_CTRL_TX_AVAIL_T *prCtrlTxAvail;
+			
+			prCtrlTxAvail = &(data->rUARTCtrlTXAVAIL);
+			
+			prCtrlTxAvail->u2RetSize = Hw_GetRemainSpace;
+		}
+			break;
+		
+		case SIO_CMD_GET_RX_AVAIL:
+		{	// Only for Buffer Mode
+			DCL_HANDLE handle;
+			UART_CTRL_RX_AVAIL_T *prCtrlRxAvail;
+			
+			prCtrlRxAvail = &(data->rUARTCtrlRXAVAIL);
+			
+			prCtrlRxAvail->u2RetSize = Dev_Mgmt[dev].size;
+			
+			// Here we invoke RxCb to send ilm and clear Notify_ILM flag in Buffer Mode
+			handle = DclSerialPort_Open(dev, 0);
+			DclSerialPort_DrvRx(handle, DRV_TTY_UT, NULL);
+			
+			// Get the Notify_ILM and this flag is cleared by above callback
+			{
+				ilm_struct current_ilm;
+			
+				msg_receive_extq(&current_ilm);
+				if (current_ilm.msg_id != MSG_ID_UART_READY_TO_READ_IND) {
+					ret_status = STATUS_FAIL;
+				}
+				destroy_ilm(&current_ilm);
+			}
+		}
+			break;
+			
+        default:
+        {
+            ret_status = STATUS_INVALID_CMD;
+        }
+            break;
+    }
+    
+    return ret_status;
+}
+
+DCL_STATUS
+_tx_done_cb(
+	DCL_HANDLE handle,
+	module_type source_id,
+	tty_io_request_t *tx_ior)
+{
+	// Just Free all gpd
+	qbmt_dest_q(tx_ior->first_gpd, tx_ior->last_gpd);
+	
+	return STATUS_OK;
+}
+
+DCL_STATUS
+_rx_cb(
+	DCL_HANDLE handle,
+	module_type source_id,
+	tty_io_request_t *rx_ior)
+{
+	DCL_DEV device;
+	
+	device = DCL_UART_GET_DEV(handle);
+	
+	Dev_Mgmt[device].Rx_Ior = rx_ior;
+	
+	return STATUS_OK;
+}
+
+DCL_STATUS
+ _drv_state_change_cb(
+	DCL_HANDLE handle,
+	tty_drv_state_e state)
+{
+	switch(state)
+	{
+		case DRV_ST_DETACHED:
+		case DRV_ST_ATTACHED:
+		default:
+			break;
+	}
+	
+	return STATUS_OK;
+}
+
+/****************************************************************************
+                Test Function
+ ***************************************************************************/
+
+#define IS_SUB_CASE_FAIL(_func) (_func(p_ret_err_str, p_ret_err_str_sz) == KAL_FALSE)
+/***********************************
+		Function Verification
+ ***********************************/
+
+kal_bool FuncVeri_Common(void *p_param, kal_char *p_ret_err_str, kal_uint32 *p_ret_err_str_sz)
+{
+	DCL_DEV device;
+	DCL_HANDLE handle;
+	DCL_STATUS status;
+	
+	/*
+	 * DclSerialPort_Initialize Test
+	 */
+	status = DclSerialPort_Initialize();
+	if (status != STATUS_OK) {
+		FAIL_MSG("Initialize Failed!");
+		return KAL_FALSE;
+	}
+	
+	/*
+	 * DclSerialPort_Open(device, flags) Test
+	 *	   - parameter
+	 *		   device	- which port you want to get handle
+	 *		   flags	- no used
+	 *
+	 * 	   - Description
+	 *		   This function is used to get handle only 
+	 *		   and do nothing with initialization setting of port
+	 *
+	 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+	 * Scenario
+	 *     Port range(P)						| Expected result
+	 *	   ============================================================
+	 *	   P < uart_port1 or P > uart_max_port	| STATUS_INVALID_DEVICE
+	 *	   uart_port1 <= P <= uart_max_port		| DCL_UART_MAGIC_NUM | device
+	 */
+	
+	for (device = 0; device < uart_port1; device++) {
+		handle = DclSerialPort_Open(device, 0);
+		if (handle != STATUS_INVALID_DEVICE) {
+			FAIL_MSG("Get handle test Failed! port # = %d", device);
+			return KAL_FALSE;			
+		}
+	}
+		
+	for (device = uart_port1; device <= uart_max_port; device++) {
+		handle = DclSerialPort_Open(device, 0);
+		if (handle != (DCL_UART_MAGIC_NUM | device)) {
+			FAIL_MSG("Get handle test Failed! port # = %d", device);
+			return KAL_FALSE;			
+		}
+	}
+
+	for (device = uart_max_port + 1; device < uart_port_null; device++) {
+		handle = DclSerialPort_Open(device, 0);
+		if (handle != STATUS_INVALID_DEVICE) {
+			FAIL_MSG("Get handle test Failed! port # = %d", device);
+			return KAL_FALSE;			
+		}
+	}
+	
+	// Check there is no assert
+	if (ut_assert_flag) {
+		ut_assert_flag = KAL_FALSE; // clear flag
+		FAIL_MSG("There is a assertion in exception. It's found at Test Case end");
+		return KAL_FALSE;
+	}
+	return KAL_TRUE;
+}
+
+kal_bool FuncVeri_DrvRegDeRegCb(void *p_param, kal_char *p_ret_err_str, kal_uint32 *p_ret_err_str_sz)
+{
+	DCL_DEV device;
+	DCL_HANDLE handle;
+	DCL_STATUS status;	
+	SIO_TYPE_T devtype;
+	Seriport_HANDLER_T drv_ut_handler;
+	
+	/*
+	 * DclSerialPort_DrvRegisterCb(handle, drv_cb)
+	 * 	   - Description
+	 *		   Register driver callback function as uart handler for TTYCore.
+	 *		   And specify device type(will affect chunkSize & others...
+	 *		   This API will make port active.
+	 *
+	 * DclSerialPort_DrvDeRegisterCb(handle)
+	 * 	   - Description
+	 *		   Clear uart handler for TTYCore.
+	 *		   This API will make port inactive.
+	 *
+	 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+	 * Scenario
+	 *     Conditions							| Expected result
+	 *	   ============================================================
+	 *	   Invalid port							| STATUS_FAIL 
+												| STATUS_INVALID_DCL_HANDLE 
+												| STATUS_INVALID_DEVICE
+	 * 	   valid port
+	 *			   drv_cb is null				| STATUS_INVALID_ARGUMENT
+	 *			   RegCb/DeRegCb				| STATUS_OK
+	 *			   Dup RegCb					| STATUS_ALREADY_OPENED
+	 *			   Dup DeRegCb					| STATUS_INVALID_OPERATION
+	 *			
+	 *	   Other Situations
+	 *		   Each port will register with each device type
+	 *	
+	 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+	 * TODO
+	 *		DeRegCb with DrvAttach
+	 */
+	
+	device = uart_port_null;
+	handle = DclSerialPort_Open(device, 0);
+	// Invalid Port Test
+	status = DclSerialPort_DrvRegisterCb(handle, &drv_ut_handler);
+	if (status != STATUS_FAIL) {
+		FAIL_MSG("Driver RegisterCb in Invalid port");
+		return KAL_FALSE;
+	}
+	status = DclSerialPort_DrvDeRegisterCb(handle);
+	if (status != STATUS_FAIL) {
+		FAIL_MSG("Driver De-RegisterCb in Invalid port");
+		return KAL_FALSE;
+	}
+	
+	// Valid Port Test
+	for (device = uart_port1; device <= uart_max_port; device++) {
+		handle = DclSerialPort_Open(device, 0);
+	
+		for (devtype = DCL_UART_TYPE; devtype < DCL_UART_DEV_TYPE_MAX; devtype++){
+			drv_ut_handler.DevType = devtype;
+			
+			// Register NULL callback (will assert)
+			drv_ut_handler.SeriportHandlerCb = NULL;
+			// Check there is no assert
+			if (ut_assert_flag) {
+				ut_assert_flag = KAL_FALSE; // clear flag
+				FAIL_MSG("There is a assertion in exception. It's found at Test Case end");
+				return KAL_FALSE;
+			}
+			status = DclSerialPort_DrvRegisterCb(handle, &drv_ut_handler);
+			if ((ut_assert_flag == KAL_FALSE) || (status != STATUS_INVALID_ARGUMENT)) {
+				FAIL_MSG("Driver Register NULL Test Failed! Device# = %d, DevType = %d", device, devtype);
+				return KAL_FALSE;
+			}
+			ut_assert_flag = KAL_FALSE;
+			
+			drv_ut_handler.SeriportHandlerCb = _drv_handler_cb;
+			
+			// First Register callback
+			status = DclSerialPort_DrvRegisterCb(handle, &drv_ut_handler);
+			if (status != STATUS_OK) {
+				FAIL_MSG("Driver Register Callback Failed! Device# = %d, DevType = %d", device, devtype);
+				return KAL_FALSE;
+			}
+			
+			// Duplicated Register callback
+			status = DclSerialPort_DrvRegisterCb(handle, &drv_ut_handler);
+			if (status != STATUS_ALREADY_OPENED) {
+				FAIL_MSG("Driver Duplicated RegisterCb Failed! Device# = %d, DevType = %d", device, devtype);
+				return KAL_FALSE;
+			}
+			
+			// First De-Register callback
+			status = DclSerialPort_DrvDeRegisterCb(handle);
+			if (status != STATUS_OK) {
+				FAIL_MSG("Driver De-RegisterCb Failed! Device# = %d, DevType = %d", device, devtype);
+				return KAL_FALSE;
+			}
+			
+			// Duplicated De-Register callback
+			status = DclSerialPort_DrvDeRegisterCb(handle);
+			if (status != STATUS_INVALID_OPERATION) {
+				FAIL_MSG("Driver Duplicated De-RegisterCb Failed! Device# = %d, DevType = %d", device, devtype);
+				return KAL_FALSE;
+			}
+			
+			/// TODO: De-RegisterCb with DrvAttach
+		}
+	}
+	
+	// Check there is no assert
+	if (ut_assert_flag) {
+		ut_assert_flag = KAL_FALSE; // clear flag
+		FAIL_MSG("There is a assertion in exception. It's found at Test Case end");
+		return KAL_FALSE;
+	}
+	return KAL_TRUE;
+}
+
+kal_bool FuncVeri_DrvAtDetach(void *p_param, kal_char *p_ret_err_str, kal_uint32 *p_ret_err_str_sz)
+{
+	DCL_DEV device;
+	DCL_HANDLE handle;
+	DCL_STATUS status;	
+	SIO_TYPE_T devtype;
+	Seriport_HANDLER_T drv_ut_handler;
+	
+	/*
+	 * DclSerialPort_DrvAttach(handle)
+	 * DclSerialPort_DrvDetach(handle)
+	 * 	   - Description
+	 *		   Change port state to attach/detach as state of driver connect/disconnect
+	 *
+	 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+	 * Scenario
+	 *     Conditions							| Expected result
+	 *	   ============================================================
+	 *	   Invalid port							| STATUS_FAIL 
+												| STATUS_INVALID_DCL_HANDLE 
+												| STATUS_DEVICE_NOT_EXIST
+	 * 	   valid port
+	 *		   port active
+	 *			   Attach/Detach				| STATUS_OK
+	 *			   Dup Attach/Detach			| STATUS_OK
+	 *		   port inactive
+	 *			   Attach/Detach				| STATUS_DEVICE_NOT_EXIST
+	 */
+
+	device = uart_port_null;
+	handle = DclSerialPort_Open(device, 0);
+	// Invalid Port Test
+	status = DclSerialPort_DrvAttach(handle);
+	if (status != STATUS_FAIL) {
+		FAIL_MSG("Driver Attach in Invalid port");
+		return KAL_FALSE;
+	}
+	status = DclSerialPort_DrvDetach(handle);
+	if (status != STATUS_FAIL) {
+		FAIL_MSG("Driver Detach in Invalid port");
+		return KAL_FALSE;
+	}
+
+	// Valid Port Test
+	for (device = uart_port1; device <= uart_max_port; device++) {
+		handle = DclSerialPort_Open(device, 0);
+	
+		// Port InActive		
+		status = DclSerialPort_DrvAttach(handle);
+		if (status != STATUS_DEVICE_NOT_EXIST) {
+			FAIL_MSG("Driver Attach with port inactive Failed! Device# = %d", device);
+			return KAL_FALSE;
+		}
+		status = DclSerialPort_DrvDetach(handle);
+		if (status != STATUS_DEVICE_NOT_EXIST) {
+			FAIL_MSG("Driver Detach with port inactive Failed! Device# = %d", device);
+			return KAL_FALSE;
+		}
+		
+		drv_ut_handler.SeriportHandlerCb = _drv_handler_cb;
+		// Port Active with each device type
+		for (devtype = DCL_UART_TYPE; devtype < DCL_UART_DEV_TYPE_MAX; devtype++){
+			drv_ut_handler.DevType = devtype;
+			
+			// Register callback (Active)
+			status = DclSerialPort_DrvRegisterCb(handle, &drv_ut_handler);
+			if (status != STATUS_OK) {
+				FAIL_MSG("Driver Register Callback Failed! Device# = %d, DevType = %d", device, devtype);
+				return KAL_FALSE;
+			}
+			
+			// First Attach
+			status = DclSerialPort_DrvAttach(handle);
+			if (status != STATUS_OK) {
+				FAIL_MSG("Driver Attach Failed! Device# = %d, DevType = %d", device, devtype);
+				return KAL_FALSE;
+			}
+			
+			//Duplicated Attach
+			status = DclSerialPort_DrvAttach(handle);
+			if (status != STATUS_OK) {
+				FAIL_MSG("Driver Duplicated Attach Failed! Device# = %d, DevType = %d", device, devtype);
+				return KAL_FALSE;
+			}
+			
+			// First Detach
+			status = DclSerialPort_DrvDetach(handle);
+			if (status != STATUS_OK) {
+				FAIL_MSG("Driver Detach Failed! Device# = %d, DevType = %d", device, devtype);
+				return KAL_FALSE;
+			}
+			
+			// Duplicated Detach
+			status = DclSerialPort_DrvDetach(handle);
+			if (status != STATUS_OK) {
+				FAIL_MSG("Driver Duplicated Detach Failed! Device# = %d, DevType = %d", device, devtype);
+				return KAL_FALSE;
+			}
+			
+			// De-Register callback (InActive port - Avoid next time RegisterCb Failed)
+			status = DclSerialPort_DrvDeRegisterCb(handle);
+			if (status != STATUS_OK) {
+				FAIL_MSG("Driver De-RegisterCb Failed! Device# = %d, DevType = %d", device, devtype);
+				return KAL_FALSE;
+			}
+		}
+	}
+	
+	// Check there is no assert
+	if (ut_assert_flag) {
+		ut_assert_flag = KAL_FALSE; // clear flag
+		FAIL_MSG("There is a assertion in exception. It's found at Test Case end");
+		return KAL_FALSE;
+	}
+	return KAL_TRUE;
+}
+
+kal_bool FuncVeri_UpInitDeinit(void *p_param, kal_char *p_ret_err_str, kal_uint32 *p_ret_err_str_sz)
+{
+	DCL_DEV device;
+	DCL_HANDLE handle;
+	DCL_STATUS status;
+	SIO_TYPE_T devtype;
+	Seriport_HANDLER_T drv_ut_handler;
+		
+	/*
+	 * DclSerialPort_UpModuleInit(handle, module_id, flag)
+	 * DclSerialPort_Control(handle, SIO_CMD_OPEN, data)
+	 * 	   - Description
+	 *		   Setup owner id and Tx/Rx path in specify port.
+	 *		   Send SIO_CMD_OPEN to let Driver know port is opened.
+	 *
+	 * DclSerialPort_UpModuleDeinit(handle)
+	 * DclSerialPort_Control(handle, SIO_CMD_CLOSE, data)
+	 * 	   - Description
+	 *		   Clear owner id and Tx/Rx path in specify port.
+	 *		   Send SIO_CMD_CLOSE to let Driver know port is closed.
+	 *
+	 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+	 * Scenario
+	 *     Conditions							| Expected result
+	 *	   ============================================================
+	 *	   Invalid port							| STATUS_FAIL 
+												| STATUS_INVALID_DCL_HANDLE 
+												| STATUS_INVALID_DEVICE
+	 * 	   valid port
+	 *			   Init/Deinit					| STATUS_OK
+	 *			   Dup Init/Deinit				| STATUS_ALREADY_OPENED/STATUS_NOT_OPENED
+	 *	
+	 *	   Other Situations
+	 *			   when Driver active/inactive
+	 *				   active with each device type
+	 *		   Kinds of Initialization
+	 * 			   New Tx, New Rx, New Tx&Rx, Conv(New API/ Conv API)
+	 *  	   Kinds of De-Initialization
+	 *  		   New API/ Conv API)
+	 *
+	 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+	 * TODO
+	 *	   In this Test Case, we only test pair of Conv Init & Conv De-Init
+	 *											   New Init & New De-Init
+	 *	   Uncovering case
+	 *		   pair of Conv Init & New De-Init
+	 *				   New Init & Conv De-Init
+	 *
+	 *	   Add them If it is needed.
+	 */
+	
+	// Conv API Test
+	{
+		UART_CTRL_OPEN_T ur_ctrl_open;	
+		UART_CTRL_CLOSE_T ur_ctrl_close;
+		char *Error_Tag = "[Conv API][Conv Tx & Conv Rx] ";
+	
+		ur_ctrl_open.u4OwenrId = MOD_TTY_UT;
+		ur_ctrl_close.u4OwenrId = MOD_TTY_UT;
+	
+		device = uart_port_null;
+		handle = DclSerialPort_Open(device, 0);
+		// Invalid Port Test
+		status = DclSerialPort_Control(handle, SIO_CMD_OPEN, (DCL_CTRL_DATA_T*) &ur_ctrl_open);
+		if (status != STATUS_FAIL) {
+			FAIL_MSG_EXT(Error_Tag, "Init in Invalid port");
+			return KAL_FALSE;
+		}
+		status = DclSerialPort_Control(handle, SIO_CMD_CLOSE, (DCL_CTRL_DATA_T*) &ur_ctrl_close);
+		if (status != STATUS_FAIL) {
+			FAIL_MSG_EXT(Error_Tag, "De-Init in Invalid port");
+			return KAL_FALSE;
+		}
+				
+		// Valid Port Test
+		for (device = uart_port1; device <= uart_max_port; device++) {
+			handle = DclSerialPort_Open(device, 0);
+		
+			// Port InActive	
+			{
+				// First Init
+				status = DclSerialPort_Control(handle, SIO_CMD_OPEN, (DCL_CTRL_DATA_T*) &ur_ctrl_open);
+				if (status != STATUS_OK) {
+					FAIL_MSG_EXT(Error_Tag, "Init in InActive Valid port");
+					return KAL_FALSE;
+				}
+				
+				// Duplicated Init
+				status = DclSerialPort_Control(handle, SIO_CMD_OPEN, (DCL_CTRL_DATA_T*) &ur_ctrl_open);
+				if (status != STATUS_ALREADY_OPENED) {
+					FAIL_MSG_EXT(Error_Tag, "Duplicated Init in InActive Valid port");
+					return KAL_FALSE;
+				}
+				
+				// First De-Init
+				status = DclSerialPort_Control(handle, SIO_CMD_CLOSE,(DCL_CTRL_DATA_T*)  &ur_ctrl_close);
+				if (status != STATUS_OK) {
+					FAIL_MSG_EXT(Error_Tag, "De-Init in InActive Valid port");
+					return KAL_FALSE;
+				}
+				
+				// Duplicated De-Init
+				status = DclSerialPort_Control(handle, SIO_CMD_CLOSE, (DCL_CTRL_DATA_T*) &ur_ctrl_close);
+				if (status != STATUS_NOT_OPENED) {
+					FAIL_MSG_EXT(Error_Tag, "Duplicated De-Init in InActive Valid port");
+					return KAL_FALSE;
+				}				
+			}
+			
+			drv_ut_handler.SeriportHandlerCb = _drv_handler_cb;
+			// Port Active with each device type
+			for (devtype = DCL_UART_TYPE; devtype < DCL_UART_DEV_TYPE_MAX; devtype++){
+				drv_ut_handler.DevType = devtype;
+				
+				// Register callback (Active)
+				status = DclSerialPort_DrvRegisterCb(handle, &drv_ut_handler);
+				if (status != STATUS_OK) {
+					FAIL_MSG_EXT(Error_Tag, "Driver Register Callback Failed! Device# = %d, DevType = %d", device, devtype);
+					return KAL_FALSE;
+				}
+				
+				// First Init
+				status = DclSerialPort_Control(handle, SIO_CMD_OPEN, (DCL_CTRL_DATA_T*) &ur_ctrl_open);
+				if (status != STATUS_OK) {
+					FAIL_MSG_EXT(Error_Tag, "Init in Active Valid port");
+					return KAL_FALSE;
+				}
+				
+				// Duplicated Init
+				status = DclSerialPort_Control(handle, SIO_CMD_OPEN, (DCL_CTRL_DATA_T*) &ur_ctrl_open);
+				if (status != STATUS_ALREADY_OPENED) {
+					FAIL_MSG_EXT(Error_Tag, "Duplicated Init in Active Valid port");
+					return KAL_FALSE;
+				}
+				
+				// First De-Init
+				status = DclSerialPort_Control(handle, SIO_CMD_CLOSE, (DCL_CTRL_DATA_T*) &ur_ctrl_close);
+				if (status != STATUS_OK) {
+					FAIL_MSG_EXT(Error_Tag, "De-Init in Active Valid port");
+					return KAL_FALSE;
+				}
+				
+				// Duplicated De-Init
+				// Here is return STATUS_OK but not STATUS_NOT_OPENED
+				///TODO: if this result of return value is BUG, please fix it.
+				status = DclSerialPort_Control(handle, SIO_CMD_CLOSE, (DCL_CTRL_DATA_T*) &ur_ctrl_close);
+				if (status != STATUS_OK) {
+					FAIL_MSG_EXT(Error_Tag, "Duplicated De-Init in Active Valid port");
+					return KAL_FALSE;
+				}
+			
+				// De-Register callback (InActive port - Avoid next time RegisterCb Failed)
+				status = DclSerialPort_DrvDeRegisterCb(handle);
+				if (status != STATUS_OK) {
+					FAIL_MSG_EXT(Error_Tag, "Driver De-RegisterCb Failed! Device# = %d, DevType = %d", device, devtype);
+					return KAL_FALSE;
+				}
+			}
+		}
+	}
+	
+	// New API Test
+	{
+		int i;
+		int flag;
+		int Path_Case[4] = {
+				0,
+				TTY_FLAG_NEW_TX,
+				TTY_FLAG_NEW_RX,
+				TTY_FLAG_NEW_TX | TTY_FLAG_NEW_RX};
+		char *Error_Tag[4] = {
+				"[New  API][Conv Tx & Conv Rx] ",
+				"[New  API][New  Tx & Conv Rx] ",
+				"[New  API][Conv Tx & New  Rx] ",
+				"[New  API][New  Tx & New  Rx] "};
+				
+		for (i = 0; i < 4; i++) {
+			flag = Path_Case[i];
+		
+			device = uart_port_null;
+			handle = DclSerialPort_Open(device, 0);
+			// Invalid Port Test
+			status = DclSerialPort_UpModuleInit(handle, MOD_TTY_UT, flag);
+			if (status != STATUS_FAIL) {
+				FAIL_MSG_EXT(Error_Tag[i], "Init in Invalid port");
+				return KAL_FALSE;
+			}
+			status = DclSerialPort_UpModuleDeinit(handle);
+			if (status != STATUS_FAIL) {
+				FAIL_MSG_EXT(Error_Tag[i], "De-Init in Invalid port");
+				return KAL_FALSE;
+			}
+					
+			
+			drv_ut_handler.SeriportHandlerCb = _drv_handler_cb;
+			// Valid Port Test
+			for (device = uart_port1; device <= uart_max_port; device++) {
+				handle = DclSerialPort_Open(device, 0);
+			
+				// Port InActive	
+				{
+					// First Init
+					status = DclSerialPort_UpModuleInit(handle, MOD_TTY_UT, flag);
+					if (status != STATUS_OK) {
+						FAIL_MSG_EXT(Error_Tag[i], "Init in InActive Valid port");
+						return KAL_FALSE;
+					}
+					
+					// Duplicated Init
+					status = DclSerialPort_UpModuleInit(handle, MOD_TTY_UT, flag);
+					if (status != STATUS_ALREADY_OPENED) {
+						FAIL_MSG_EXT(Error_Tag[i], "Duplicated Init in InActive Valid port");
+						return KAL_FALSE;
+					}
+					
+					// First De-Init
+					status = DclSerialPort_UpModuleDeinit(handle);
+					if (status != STATUS_OK) {
+						FAIL_MSG_EXT(Error_Tag[i], "De-Init in InActive Valid port");
+						return KAL_FALSE;
+					}
+					
+					// Duplicated De-Init
+					status = DclSerialPort_UpModuleDeinit(handle);
+					if (status != STATUS_NOT_OPENED) {
+						FAIL_MSG_EXT(Error_Tag[i], "Duplicated De-Init in InActive Valid port");
+						return KAL_FALSE;
+					}				
+				}
+				
+				// Port Active with each device type
+				for (devtype = DCL_UART_TYPE; devtype < DCL_UART_DEV_TYPE_MAX; devtype++){
+					drv_ut_handler.DevType = devtype;
+					
+					// Register callback (Active)
+					status = DclSerialPort_DrvRegisterCb(handle, &drv_ut_handler);
+					if (status != STATUS_OK) {
+						FAIL_MSG_EXT(Error_Tag[i], "Driver Register Callback Failed! Device# = %d, DevType = %d", device, devtype);
+						return KAL_FALSE;
+					}
+					
+					// First Init
+					status = DclSerialPort_UpModuleInit(handle, MOD_TTY_UT, flag);
+					if (status != STATUS_OK) {
+						FAIL_MSG_EXT(Error_Tag[i], "Init in Active Valid port");
+						return KAL_FALSE;
+					}
+					
+					// Duplicated Init
+					status = DclSerialPort_UpModuleInit(handle, MOD_TTY_UT, flag);
+					if (status != STATUS_ALREADY_OPENED) {
+						FAIL_MSG_EXT(Error_Tag[i], "Duplicated Init in Active Valid port");
+						return KAL_FALSE;
+					}
+					
+					// First De-Init
+					status = DclSerialPort_UpModuleDeinit(handle);
+					if (status != STATUS_OK) {
+						FAIL_MSG_EXT(Error_Tag[i], "De-Init in Active Valid port");
+						return KAL_FALSE;
+					}
+					
+					// Duplicated De-Init
+					status = DclSerialPort_UpModuleDeinit(handle);
+					if (status != STATUS_NOT_OPENED) {
+						FAIL_MSG_EXT(Error_Tag[i], "Duplicated De-Init in Active Valid port");
+						return KAL_FALSE;
+					}
+				
+					// De-Register callback (InActive port - Avoid next time RegisterCb Failed)
+					status = DclSerialPort_DrvDeRegisterCb(handle);
+					if (status != STATUS_OK) {
+						FAIL_MSG_EXT(Error_Tag[i], "Driver De-RegisterCb Failed! Device# = %d, DevType = %d", device, devtype);
+						return KAL_FALSE;
+					}
+				}
+			}
+		}
+	}
+
+	// Check there is no assert
+	if (ut_assert_flag) {
+		ut_assert_flag = KAL_FALSE; // clear flag
+		FAIL_MSG("There is a assertion in exception. It's found at Test Case end");
+		return KAL_FALSE;
+	}
+	return KAL_TRUE;
+}
+
+kal_bool FuncVeri_UpRegCb(void *p_param, kal_char *p_ret_err_str, kal_uint32 *p_ret_err_str_sz)
+{
+	DCL_DEV device;
+	DCL_HANDLE handle;
+	DCL_STATUS status;
+	
+	/*
+	 * DclSerialPort_UpModuleRegisterCb(handle, rx_cb, tx_done_cb, drv_state_change)
+	 * 	   - Description
+	 *		   Register callback in specify port.
+	 *
+	 *		   This API is independent with active/inactive.
+	 *
+	 *	   - Warning
+	 *		   Condition 1:
+	 *			   This API is for New Upper Module,
+	 *			   Conv Upper Module no need to use it.
+	 *			   There is nothing verification of it.
+	 *
+	 *		   Condition 2:
+	 *			   This API need to be used after port initializing, 
+	 *			   but there is nothing verification of it.
+	 *
+	 *			   If you use this API before port initialized,
+	 *			   it maybe cause some unexpected result.
+	 *
+	 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+	 * Scenario
+	 *     Conditions							| Expected result
+	 *	   ============================================================
+	 *	   Invalid port							| STATUS_FAIL 
+												| STATUS_INVALID_DCL_HANDLE 
+												| STATUS_INVALID_DEVICE
+	 * 	   valid port
+	 *		   RegCb/Dup RegCb					| STATUS_OK
+	 *		   Assert Condition					| ASSERT
+	 *			 - Conv Rx & Rx_Cb is not null
+	 *			 - New  Rx & Rx_Cb is null
+	 *			 - Conv Tx & Tx_Done_Cb is not null
+	 *			 - Conv Tx & Conv Rx & drv_state_change_cb is not null
+	 *			 - (New Tx or New Rx) & drv_state_change_cb is null
+	 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+	 * TODO
+	 *	   In this Test Case, we only test for New Tx/Rx case and assertion case
+	 *
+	 *	   The warning as mentioned above, if that is important, please add it in TTYCore.
+	 */
+	
+	device = uart_port_null;
+	handle = DclSerialPort_Open(device, 0);
+	// Invalid Port Test
+	status = DclSerialPort_UpModuleRegisterCb(handle, _rx_cb, _tx_done_cb, _drv_state_change_cb);
+	if (status != STATUS_FAIL) {
+		FAIL_MSG("Upper Module RegisterCb in Invalid port");
+		return KAL_FALSE;
+	}
+	
+	// Valid Port Test
+	for (device = uart_port1; device <= uart_max_port; device++) {
+		handle = DclSerialPort_Open(device, 0);
+		
+		// Init with New Tx & New Rx Path
+		status = DclSerialPort_UpModuleInit(handle, MOD_TTY_UT, TTY_FLAG_NEW_TX | TTY_FLAG_NEW_RX);
+		if (status != STATUS_OK) {
+			FAIL_MSG("Init New Tx & New Rx in Valid port");
+			return KAL_FALSE;
+		}
+		
+		// First Register callback
+		status = DclSerialPort_UpModuleRegisterCb(handle, _rx_cb, _tx_done_cb, _drv_state_change_cb);
+		if (status != STATUS_OK) {
+			FAIL_MSG("Upper Module RegisterCb in Valid port");
+			return KAL_FALSE;
+		}
+		// Duplicated Register callback with TxDoneCb is NULL
+		status = DclSerialPort_UpModuleRegisterCb(handle, _rx_cb, NULL, _drv_state_change_cb);
+		if (status != STATUS_OK) {
+			FAIL_MSG("Upper Module Duplicated RegisterCb in Valid port and TxDoneCb is NULL");
+			return KAL_FALSE;
+		}	
+		
+		// De-Init - Avoid next time Init Failed)
+		status = DclSerialPort_UpModuleDeinit(handle);
+		if (status != STATUS_OK) {
+			FAIL_MSG("De-Init New Tx & New Rx in Valid port");
+			return KAL_FALSE;
+		}
+	}
+	
+	// Assertion Case
+	// 	   Conv Rx & Rx_Cb is not null
+	// 	   Conv Tx & Tx_Done_Cb is not null
+	// 	   Conv Tx & Conv Rx & drv_state_change_cb is not null
+	for (device = uart_port1; device <= uart_max_port; device++) {
+		handle = DclSerialPort_Open(device, 0);
+		
+		// Init with Conv Tx & Conv Rx Path
+		status = DclSerialPort_UpModuleInit(handle, MOD_TTY_UT, 0);
+		if (status != STATUS_OK) {
+			FAIL_MSG("Init Conv Tx & Conv Rx in Valid port");
+			return KAL_FALSE;
+		}
+		
+		// Register callback - Conv Rx & Rx_Cb is not null
+		// Check there is no assert
+		if (ut_assert_flag) {
+			ut_assert_flag = KAL_FALSE; // clear flag
+			FAIL_MSG("There is a assertion in exception. It's found at Test Case end");
+			return KAL_FALSE;
+		}
+		status = DclSerialPort_UpModuleRegisterCb(handle, _rx_cb, NULL, NULL);
+		if (ut_assert_flag == KAL_FALSE) {
+			FAIL_MSG("Upper Module Register Callback");
+			return KAL_FALSE;
+		}
+		ut_assert_flag = KAL_FALSE;
+		
+		// Register callback - Conv Tx & Tx_Done_Cb is not null
+		// Check there is no assert
+		if (ut_assert_flag) {
+			ut_assert_flag = KAL_FALSE; // clear flag
+			FAIL_MSG("There is a assertion in exception. It's found at Test Case end");
+			return KAL_FALSE;
+		}
+		status = DclSerialPort_UpModuleRegisterCb(handle, NULL, _tx_done_cb, NULL);
+		if (ut_assert_flag == KAL_FALSE) {
+			FAIL_MSG("Upper Module Register Callback");
+			return KAL_FALSE;
+		}
+		ut_assert_flag = KAL_FALSE;
+		
+		// Register callback - Conv Tx & Conv Rx & drv_state_change_cb is not null
+		// Check there is no assert
+		if (ut_assert_flag) {
+			ut_assert_flag = KAL_FALSE; // clear flag
+			FAIL_MSG("There is a assertion in exception. It's found at Test Case end");
+			return KAL_FALSE;
+		}
+		status = DclSerialPort_UpModuleRegisterCb(handle, NULL, NULL, _drv_state_change_cb);
+		if (ut_assert_flag == KAL_FALSE) {
+			FAIL_MSG("Upper Module Register Callback");
+			return KAL_FALSE;
+		}
+		ut_assert_flag = KAL_FALSE;
+		
+		// De-Init - Avoid next time Init Failed)
+		status = DclSerialPort_UpModuleDeinit(handle);
+		if (status != STATUS_OK) {
+			FAIL_MSG("De-Init Conv Tx & Conv Rx in Valid port");
+			return KAL_FALSE;
+		}
+	}
+	//     New  Rx & Rx_Cb is null
+	//     (New Tx or New Rx) & drv_state_change_cb is null
+	for (device = uart_port1; device <= uart_max_port; device++) {
+		handle = DclSerialPort_Open(device, 0);
+		
+		// Init with New Rx Path
+		status = DclSerialPort_UpModuleInit(handle, MOD_TTY_UT, TTY_FLAG_NEW_RX);
+		if (status != STATUS_OK) {
+			FAIL_MSG("Init New Rx in Valid port");
+			return KAL_FALSE;
+		}
+		
+		// Register callback - New  Rx & Rx_Cb is null
+		// Check there is no assert
+		if (ut_assert_flag) {
+			ut_assert_flag = KAL_FALSE; // clear flag
+			FAIL_MSG("There is a assertion in exception. It's found at Test Case end");
+			return KAL_FALSE;
+		}
+		status = DclSerialPort_UpModuleRegisterCb(handle, NULL, _tx_done_cb, _drv_state_change_cb);
+		if (ut_assert_flag == KAL_FALSE) {
+			FAIL_MSG("Upper Module Register Callback");
+			return KAL_FALSE;
+		}
+		ut_assert_flag = KAL_FALSE;
+		
+		// Register callback - (New Tx or New Rx) & drv_state_change_cb is null
+		// Check there is no assert
+		if (ut_assert_flag) {
+			ut_assert_flag = KAL_FALSE; // clear flag
+			FAIL_MSG("There is a assertion in exception. It's found at Test Case end");
+			return KAL_FALSE;
+		}
+		status = DclSerialPort_UpModuleRegisterCb(handle, _rx_cb, _tx_done_cb, NULL);
+		if (ut_assert_flag == KAL_FALSE) {
+			FAIL_MSG("Upper Module Register Callback");
+			return KAL_FALSE;
+		}
+		ut_assert_flag = KAL_FALSE;
+		
+		// De-Init - Avoid next time Init Failed)
+		status = DclSerialPort_UpModuleDeinit(handle);
+		if (status != STATUS_OK) {
+			FAIL_MSG("De-Init New Rx in Valid port");
+			return KAL_FALSE;
+		}
+	}
+
+	// Check there is no assert
+	if (ut_assert_flag) {
+		ut_assert_flag = KAL_FALSE; // clear flag
+		FAIL_MSG("There is a assertion in exception. It's found at Test Case end");
+		return KAL_FALSE;
+	}
+	return KAL_TRUE;
+}
+
+kal_bool FuncVeri_ChangeOwner(void *p_param, kal_char *p_ret_err_str, kal_uint32 *p_ret_err_str_sz)
+{
+	DCL_DEV device;
+	DCL_STATUS status;
+    DCL_HANDLE handle;
+	SIO_TYPE_T devtype;
+	UART_CTRL_OPEN_T ur_ctrl_open;
+	UART_CTRL_OWNER_T ur_ctrl_owner;	
+	Seriport_HANDLER_T drv_ut_handler;
+	
+	/*
+	 * DclSerialPort_Control(handle, SIO_CMD_SET_OWNER, data)
+	 * 	   - Description
+	 *		   It will flush all Tx/Rx gpd, then change port owner.
+	 *		   
+	 *		   This API will be invoked by new owner but not original owner.
+	 *		   If port will change to convention owner, you just call this API.
+	 *		   Or change to New Path owner, you must call the following two API.
+	 *
+	 * DclSerialPort_UpModuleReinit(handle, module_id, flag)
+	 * 	   - Description
+	 *		   Re-Initializing the port setting without closing port.
+	 *		   Reset flags and Re-specify the Path of new owner.
+	 * DclSerialPort_UpModuleRegisterCb(handle, rx_cb, tx_done_cb, drv_state_change_cb)
+	 * 	   - Description
+	 *		   Register Callback function for new owner.
+	 *
+	 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+	 * Scenario
+	 *     Conditions							| Expected result
+	 *	   ============================================================
+	 *	   Invalid port							| STATUS_FAIL 
+												| STATUS_INVALID_DCL_HANDLE 
+												| STATUS_INVALID_DEVICE
+	 * 	   valid port
+	 *		   port InActive					| STATUS_DEVICE_NOT_EXIST
+	 *		   port Active with Attach/Detach	| STATUS_OK
+	 *
+	 * Other Conditions
+	 *	   4 types
+	 *		   Conv to Conv, Conv to New, New to Conv, New to New
+	 */
+
+	device = uart_port_null;
+	handle = DclSerialPort_Open(device, 0);
+	ur_ctrl_owner.u4OwenrId = MOD_TTY_UT;
+	// Invalid Port Test
+	status = DclSerialPort_Control(handle, SIO_CMD_SET_OWNER, (DCL_CTRL_DATA_T*) &ur_ctrl_owner);
+	if (status != STATUS_FAIL) {
+		FAIL_MSG("Change owner in Invalid port");
+		return KAL_FALSE;
+	}
+	
+	
+	drv_ut_handler.SeriportHandlerCb = _drv_handler_cb;
+	// Valid Port Test
+	// Port InActive
+	for (device = uart_port1; device <= uart_max_port; device++) {
+		handle = DclSerialPort_Open(device, 0);
+		
+		status = DclSerialPort_Control(handle, SIO_CMD_SET_OWNER, (DCL_CTRL_DATA_T*) &ur_ctrl_owner);
+		if (status != STATUS_DEVICE_NOT_EXIST) {
+			FAIL_MSG("Change owner with port InActive in Valid port");
+			return KAL_FALSE;
+		}
+	}
+	
+	// Port Active
+	for (device = uart_port1; device <= uart_max_port; device++) {
+		handle = DclSerialPort_Open(device, 0);
+			
+		// Port Active with each device type
+		for (devtype = DCL_UART_TYPE; devtype < DCL_UART_DEV_TYPE_MAX; devtype++){
+			drv_ut_handler.DevType = devtype;
+			
+			// Register callback (Active)
+			status = DclSerialPort_DrvRegisterCb(handle, &drv_ut_handler);
+			if (status != STATUS_OK) {
+				FAIL_MSG("Driver Register Callback Failed! Device# = %d, DevType = %d", device, devtype);
+				return KAL_FALSE;
+			}
+			
+			// Conv to Conv
+			{
+				char * Error_Tag = "[Conv to Conv] ";
+				
+				ur_ctrl_open.u4OwenrId = MOD_TTY_UT;
+				status = DclSerialPort_Control(handle, SIO_CMD_OPEN, (DCL_CTRL_DATA_T*) &ur_ctrl_open);
+				if (status != STATUS_OK) {
+					FAIL_MSG_EXT(Error_Tag, "Conventional initialization");
+					return KAL_FALSE;
+				}
+				
+				ur_ctrl_owner.u4OwenrId = MOD_TTY_UT;
+				status = DclSerialPort_Control(handle, SIO_CMD_SET_OWNER, (DCL_CTRL_DATA_T*) &ur_ctrl_owner);
+				if (status != STATUS_OK) {
+					FAIL_MSG_EXT(Error_Tag, "Change owner to Conv owner");
+					return KAL_FALSE;
+				}
+				
+				status = DclSerialPort_UpModuleDeinit(handle);
+				if (status != STATUS_OK) {
+					FAIL_MSG_EXT(Error_Tag, "De-initialization");
+					return KAL_FALSE;
+				}
+			}
+			// Conv to New
+			{
+				int flag = TTY_FLAG_NEW_TX | TTY_FLAG_NEW_RX;
+				char * Error_Tag = "[Conv to New] ";
+				
+				ur_ctrl_open.u4OwenrId = MOD_TTY_UT;
+				status = DclSerialPort_Control(handle, SIO_CMD_OPEN, (DCL_CTRL_DATA_T*) &ur_ctrl_open);
+				if (status != STATUS_OK) {
+					FAIL_MSG_EXT(Error_Tag, "Conventional initialization");
+					return KAL_FALSE;
+				}
+				
+				ur_ctrl_owner.u4OwenrId = MOD_TTY_UT;
+				status = DclSerialPort_Control(handle, SIO_CMD_SET_OWNER, (DCL_CTRL_DATA_T*) &ur_ctrl_owner);
+				if (status != STATUS_OK) {
+					FAIL_MSG_EXT(Error_Tag, "Change owner to New owner");
+					return KAL_FALSE;
+				}
+				
+				status = DclSerialPort_UpModuleReinit(handle, MOD_TTY_UT, flag);
+				if (status != STATUS_OK) {
+					FAIL_MSG_EXT(Error_Tag, "New owner Re-Init");
+					return KAL_FALSE;
+				}
+				
+				status = DclSerialPort_UpModuleRegisterCb(handle, _rx_cb, _tx_done_cb, _drv_state_change_cb);
+				if (status != STATUS_OK) {
+					FAIL_MSG_EXT(Error_Tag, "New owner Re-Register Callback");
+					return KAL_FALSE;
+				}
+				
+				status = DclSerialPort_UpModuleDeinit(handle);
+				if (status != STATUS_OK) {
+					FAIL_MSG_EXT(Error_Tag, "De-initialization");
+					return KAL_FALSE;
+				}
+			}
+			// New to Conv
+			{
+				int flag = TTY_FLAG_NEW_TX | TTY_FLAG_NEW_RX;
+				char * Error_Tag = "[New to Conv] ";
+				
+				
+				status = DclSerialPort_UpModuleInit(handle, MOD_TTY_UT, flag);
+				if (status != STATUS_OK) {
+					FAIL_MSG_EXT(Error_Tag, "New Module initialization");
+					return KAL_FALSE;
+				}
+				
+				status = DclSerialPort_UpModuleRegisterCb(handle, _rx_cb, _tx_done_cb, _drv_state_change_cb);
+				if (status != STATUS_OK) {
+					FAIL_MSG_EXT(Error_Tag, "New Module Register Callback");
+					return KAL_FALSE;
+				}
+				
+				ur_ctrl_owner.u4OwenrId = MOD_TTY_UT;
+				status = DclSerialPort_Control(handle, SIO_CMD_SET_OWNER, (DCL_CTRL_DATA_T*) &ur_ctrl_owner);
+				if (status != STATUS_OK) {
+					FAIL_MSG_EXT(Error_Tag, "Change owner to Conv owner");
+					return KAL_FALSE;
+				}
+								
+				status = DclSerialPort_UpModuleDeinit(handle);
+				if (status != STATUS_OK) {
+					FAIL_MSG_EXT(Error_Tag, "De-initialization");
+					return KAL_FALSE;
+				}
+			}
+			// New to New
+			{
+				int flag = TTY_FLAG_NEW_TX | TTY_FLAG_NEW_RX;
+				char * Error_Tag = "[New to New] ";
+				
+				
+				status = DclSerialPort_UpModuleInit(handle, MOD_TTY_UT, flag);
+				if (status != STATUS_OK) {
+					FAIL_MSG_EXT(Error_Tag, "New Module initialization");
+					return KAL_FALSE;
+				}
+				
+				status = DclSerialPort_UpModuleRegisterCb(handle, _rx_cb, _tx_done_cb, _drv_state_change_cb);
+				if (status != STATUS_OK) {
+					FAIL_MSG_EXT(Error_Tag, "New Module Register Callback");
+					return KAL_FALSE;
+				}
+				
+				ur_ctrl_owner.u4OwenrId = MOD_TTY_UT;
+				status = DclSerialPort_Control(handle, SIO_CMD_SET_OWNER, (DCL_CTRL_DATA_T*) &ur_ctrl_owner);
+				if (status != STATUS_OK) {
+					FAIL_MSG_EXT(Error_Tag, "Change owner to New owner");
+					return KAL_FALSE;
+				}
+				
+				status = DclSerialPort_UpModuleReinit(handle, MOD_TTY_UT, flag);
+				if (status != STATUS_OK) {
+					FAIL_MSG_EXT(Error_Tag, "New owner Re-Init");
+					return KAL_FALSE;
+				}
+				
+				status = DclSerialPort_UpModuleRegisterCb(handle, _rx_cb, _tx_done_cb, _drv_state_change_cb);
+				if (status != STATUS_OK) {
+					FAIL_MSG_EXT(Error_Tag, "New owner Re-Register Callback");
+					return KAL_FALSE;
+				}
+				
+				status = DclSerialPort_UpModuleDeinit(handle);
+				if (status != STATUS_OK) {
+					FAIL_MSG_EXT(Error_Tag, "De-initialization");
+					return KAL_FALSE;
+				}
+			}
+			
+			// De-Register callback (InActive port - Avoid next time RegisterCb Failed)
+			status = DclSerialPort_DrvDeRegisterCb(handle);
+			if (status != STATUS_OK) {
+				FAIL_MSG("Driver De-RegisterCb Failed! Device# = %d, DevType = %d", device, devtype);
+				return KAL_FALSE;
+			}
+		}
+	}
+	
+	
+	return KAL_TRUE;
+}
+
+kal_bool FuncVeri_Misc(void *p_param, kal_char *p_ret_err_str, kal_uint32 *p_ret_err_str_sz)
+{
+	DCL_HANDLE handle;
+	/*
+	 * This Test Case Just For Function Coverage.
+	 * Nothing to be tested here.
+	 */
+	
+	handle = DclSerialPort_Open(uart_port_null, 0);
+	
+	DclSerialPort_Close(handle);
+	DclSerialPort_Configure(handle, NULL);
+	
+	return KAL_TRUE;
+}
+
+/***********************************
+		DataPath Verification
+ ***********************************/
+
+ /*
+ * In Data path verification,
+ * We won't Test with each port, just test one to represent all.
+ *
+ * In each sub-case,
+ * We will Test driver state change callback by initialing upper module 
+ * before driver register its callback.
+ *
+ * Before the operation of data transfer, it never check driver is attach
+ * due to driver attach is expected here.
+ */
+ 
+/**************
+	Sub-Case
+ **************/
+kal_bool DataPath_Setup(DCL_HANDLE handle, SIO_TYPE_T devtype, int flag) 
+{
+	DCL_STATUS status;
+	Seriport_HANDLER_T drv_ut_handler;
+	
+	// Upper Module Initialize		
+	status = DclSerialPort_UpModuleInit(handle, MOD_TTY_UT, flag);
+	if (status != STATUS_OK)
+		return KAL_FALSE;
+
+	// Only New Upper Module Need to register callback
+	if (flag) {
+		switch (flag) {
+			case TTY_FLAG_NEW_TX:
+				status = DclSerialPort_UpModuleRegisterCb(handle, NULL, _tx_done_cb, _drv_state_change_cb);
+				break;
+			case TTY_FLAG_NEW_RX:
+				status = DclSerialPort_UpModuleRegisterCb(handle, _rx_cb, NULL, _drv_state_change_cb);
+				break;
+			case TTY_FLAG_NEW_TX | TTY_FLAG_NEW_RX:
+				status = DclSerialPort_UpModuleRegisterCb(handle, _rx_cb, _tx_done_cb, _drv_state_change_cb);
+				break;
+			default:
+				status = STATUS_FAIL;
+				break;
+		}
+	
+		if (status != STATUS_OK)
+			return KAL_FALSE;
+	}
+	
+	// Driver Register callback	& Attach	
+	drv_ut_handler.DevType = devtype;
+	drv_ut_handler.SeriportHandlerCb = _drv_handler_cb;
+	
+	status = DclSerialPort_DrvRegisterCb(handle, &drv_ut_handler);
+	if (status != STATUS_OK)
+		return KAL_FALSE;
+		
+	status = DclSerialPort_DrvAttach(handle);
+	if (status != STATUS_OK)
+		return KAL_FALSE;
+		
+	return KAL_TRUE;
+}
+
+kal_bool DataPath_Close(DCL_HANDLE handle)
+{
+	DCL_STATUS status;
+
+	// Upper Module DeInit
+	status = DclSerialPort_UpModuleDeinit(handle);
+	if (status != STATUS_OK)
+		return KAL_FALSE;
+		
+	// Driver Detatch
+	status = DclSerialPort_DrvDetach(handle);
+	if (status != STATUS_OK)
+		return KAL_FALSE;
+	
+	// Driver DeRegister Callback
+	status = DclSerialPort_DrvDeRegisterCb(handle);
+	if (status != STATUS_OK)
+		return KAL_FALSE;
+	
+	return KAL_TRUE;
+}
+
+// Directly Path Sub-Case
+kal_bool ConvTxPath(kal_char *p_ret_err_str, kal_uint32 *p_ret_err_str_sz)
+{
+	DCL_DEV device;
+	DCL_STATUS status;
+    DCL_HANDLE handle;
+	SIO_TYPE_T devtype;
+	kal_bool data_corrupt;
+
+	// Setup Port & Driver Type
+	device = uart_port1;
+	devtype = DCL_UART_USB_TYPE;		// Driver type is GPD_DRV_TYPE
+	data_corrupt = KAL_FALSE;
+	
+	// Get handle
+	handle = DclSerialPort_Open(device, 0);
+	
+	// Upper Module Initialize & Driver Register callback and then Attach
+	DataPath_Setup(handle, devtype, 0);
+
+	// if Upper Module is conventional & not buffer mode, driver will using ilm to inform upper module driver attach.
+	{
+		ilm_struct current_ilm;
+
+		msg_receive_extq(&current_ilm);
+		if (current_ilm.msg_id != MSG_ID_UART_PLUGIN_IND) {
+			destroy_ilm(&current_ilm);
+			return KAL_FALSE;
+		}
+		destroy_ilm(&current_ilm);
+	}
+
+	// Conventional Tx Path
+	// Send Tx Data -> TxDoneCb -> Get "Ready to Write" ilm
+	{
+		UART_CTRL_PUT_BYTES_T ur_ctrl_putbytes;
+		char SendBuff[UT_TEST_SIZE];
+		int datalen;
+		int offset;
+		int i;
+		
+		// Clear Hardware Buffer
+		Hw_ClearBuff(device);
+		
+		// Prepare Data to Send
+		datalen = UT_TEST_SIZE;
+		for (i = 0; i < datalen; i++) {
+			SendBuff[i] = i & UT_DATA_MASK;
+		}
+		
+		// Setup Tx Buffer Structure
+		offset = 0;
+		ur_ctrl_putbytes.u4OwenrId = MOD_TTY_UT;
+		ur_ctrl_putbytes.puBuffaddr = SendBuff;
+		ur_ctrl_putbytes.u2Length = datalen;
+		
+		// Sending Data Until Sending Complete
+		do {
+			// Dummy Upper Module
+			{
+				DclSerialPort_Control(handle, SIO_CMD_PUT_BYTES, (DCL_CTRL_DATA_T*) &ur_ctrl_putbytes);
+				offset += ur_ctrl_putbytes.u2RetSize;
+				
+				// Update Tx Buffer Structure
+				ur_ctrl_putbytes.puBuffaddr = SendBuff + offset;
+				ur_ctrl_putbytes.u2Length = datalen - offset;
+			}
+			
+			// Dummy Driver
+			{
+				// Return Tx GPD to TTYCore
+				Tx_Flush_Gpd(device);
+			}
+
+			// Dummy Upper Module
+			{
+				// In conventional path, _tty_tx_done_cb will send ilm to inform upper module.
+				// when data buffer have the remaining data still haven't be sent.
+				if (offset < datalen) {
+					ilm_struct current_ilm;
+				
+					msg_receive_extq(&current_ilm);
+					if (current_ilm.msg_id != MSG_ID_UART_READY_TO_WRITE_IND) {
+						destroy_ilm(&current_ilm);
+						return KAL_FALSE;
+					}
+					destroy_ilm(&current_ilm);
+				}
+			}
+		} while (offset < datalen);
+		
+		// Compare data with Hardware Buffer
+		for (i = 0; i < datalen; i++) {
+			if (SendBuff[i] ^ Dev_Mgmt[device].HwBuff[i]) {
+				data_corrupt = KAL_TRUE;
+				break;
+			}				
+		}
+	}
+		
+	// Upper Module DeInit & Driver Detatch & DeRegister Callback
+	DataPath_Close(handle);
+	
+	// Check data no corrupt
+	if (data_corrupt) {
+		FAIL_MSG("[ConvTxPath] Data Corrupt in Device# = %d, DevType = %d", device, devtype);
+		return KAL_FALSE;
+	}
+		
+	// Check there is no assert
+	if (ut_assert_flag) {
+		ut_assert_flag = KAL_FALSE; // clear flag
+		FAIL_MSG("[ConvTxPath] There is a assertion in exception. It's found at Test Case end");
+		return KAL_FALSE;
+	}
+	return KAL_TRUE;
+}
+
+kal_bool ConvRxPath(kal_char *p_ret_err_str, kal_uint32 *p_ret_err_str_sz)
+{
+	DCL_DEV device;
+	DCL_STATUS status;
+    DCL_HANDLE handle;
+	SIO_TYPE_T devtype;
+	kal_bool data_corrupt;
+
+	// Setup Port & Driver Type
+	device = uart_port1;
+	devtype = DCL_UART_USB_TYPE;		// Driver type is GPD_DRV_TYPE
+	data_corrupt = KAL_FALSE;
+	
+	// Get handle
+	handle = DclSerialPort_Open(device, 0);
+
+	// Upper Module Initialize & Driver Register callback and then Attach
+	DataPath_Setup(handle, devtype, 0);
+
+	// if Upper Module is conventional & not buffer mode, driver will using ilm to inform upper module driver attach.
+	{
+		ilm_struct current_ilm;
+
+		msg_receive_extq(&current_ilm);
+		if (current_ilm.msg_id != MSG_ID_UART_PLUGIN_IND) {
+			destroy_ilm(&current_ilm);
+			return KAL_FALSE;
+		}
+		destroy_ilm(&current_ilm);
+	}
+	
+	// Conventional Rx Path
+	// Prepare Rx Data -> RxCb -> Get "Ready to Read" ilm -> Get Rx Data
+	{
+		UART_CTRL_GET_BYTES_T ur_ctrl_getbytes;
+		char RecvBuff[UT_TEST_SIZE];
+		int datalen;
+		int offset;
+		int i;
+		
+		// Clear Hardware Buffer
+		Hw_ClearBuff(device);
+		
+		// Prepare Rx Data
+		datalen = UT_TEST_SIZE;
+		for (i = 0; i < datalen; i++) {
+			Dev_Mgmt[device].HwBuff[i] = i & UT_DATA_MASK;
+		}
+		Dev_Mgmt[device].size = datalen;
+		
+		// Setup Rx Buffer Structure
+		offset = 0;
+		ur_ctrl_getbytes.u4OwenrId = MOD_TTY_UT;
+		ur_ctrl_getbytes.puBuffaddr = RecvBuff;
+		ur_ctrl_getbytes.u2Length = datalen;
+		
+		// Receiving Data Until Data empty in Hardware
+		do {
+			// Dummy Hardware Operation
+			{
+				// Copy Data to Driver Rx GPD in the Rx Queue
+				Hw_PopDataToRxQue(device);
+			}
+			
+			// Dummy Driver 
+			{
+				// Get Rx GPDs(Contain Received Data) by De-Q
+				void * ior = Rx_DeQueToIor(device);
+				// Rx callback to send ior to tty
+				if (ior) {
+					DclSerialPort_DrvRx(handle, DRV_TTY_UT, ior);
+				}
+			}
+						
+			// Dummy Upper Module
+			{
+				// In conventional path, _tty_rx_cb will send ilm to inform upper module data ready to read.
+				{
+					ilm_struct current_ilm;
+				
+					msg_receive_extq(&current_ilm);
+					if (current_ilm.msg_id != MSG_ID_UART_READY_TO_READ_IND) {
+						destroy_ilm(&current_ilm);
+						return KAL_FALSE;
+					}	
+					destroy_ilm(&current_ilm);
+				}
+			
+				// Get Data
+				DclSerialPort_Control(handle, SIO_CMD_GET_BYTES, (DCL_CTRL_DATA_T*) &ur_ctrl_getbytes);
+				offset += ur_ctrl_getbytes.u2RetSize;
+				
+				// Update Rx Buffer Structure 
+				ur_ctrl_getbytes.puBuffaddr = RecvBuff + offset;
+				ur_ctrl_getbytes.u2Length = datalen - offset;
+			}
+		} while (Dev_Mgmt[device].size);
+		
+		// Compare data with Hardware Buffer
+		for (i = 0; i < datalen; i++) {
+			if (RecvBuff[i] ^ Dev_Mgmt[device].HwBuff[i]) {
+				data_corrupt = KAL_TRUE;
+				break;
+			}				
+		}
+	}
+		
+	// Upper Module DeInit & Driver Detatch & DeRegister Callback
+	DataPath_Close(handle);
+	
+	// Check data no corrupt
+	if (data_corrupt) {
+		FAIL_MSG("[ConvRxPath] Data Corrupt in Device# = %d, DevType = %d", device, devtype);
+		return KAL_FALSE;
+	}
+	
+	// Check there is no assert
+	if (ut_assert_flag) {
+		ut_assert_flag = KAL_FALSE; // clear flag
+		FAIL_MSG("[ConvRxPath] There is a assertion in exception. It's found at Test Case end");
+		return KAL_FALSE;
+	}
+	return KAL_TRUE;
+}
+
+kal_bool NewTxPath(kal_char *p_ret_err_str, kal_uint32 *p_ret_err_str_sz)
+{
+	DCL_DEV device;
+	DCL_STATUS status;
+    DCL_HANDLE handle;
+	SIO_TYPE_T devtype;
+	kal_bool data_corrupt;
+
+	// Setup Port & Driver Type
+	device = uart_port1;
+	devtype = DCL_UART_USB_TYPE;		// Driver type is GPD_DRV_TYPE
+	data_corrupt = KAL_FALSE;
+	
+	// Get handle
+	handle = DclSerialPort_Open(device, 0);
+	
+	// Upper Module Initialize & Driver Register callback and then Attach
+	DataPath_Setup(handle, devtype, TTY_FLAG_NEW_TX);
+	
+	// New Tx Path
+	// Send Tx Data -> TxDoneCb(For free gpds)
+	{
+		char SendBuff[UT_TEST_SIZE];
+		int datalen;
+		int offset;
+		int i;
+		
+		// Clear Hardware Buffer
+		Hw_ClearBuff(device);
+		
+		// Prepare Data to Send
+		datalen = UT_TEST_SIZE;
+		for (i = 0; i < datalen; i++) {
+			SendBuff[i] = i & UT_DATA_MASK;
+		}
+		
+		// Setup Tx Buffer Structure
+		offset = 0;
+		
+		// Sending Data Until Sending Complete
+		do {
+			// Dummy Upper Module
+			{
+				void *gpd_t;
+				void *p_head;
+				void *p_tail;
+				tty_io_request_t *ior;
+				int gpd_num = 2;
+				
+				// Create gpds for ior
+				// GPD_TYPE: QBM_TYPE_TTY_INT
+				// GPD_LEN: QBM_TTY_XXX_DATA_LEN(1024)
+				qbmt_alloc_q_no_tail(QBM_TYPE_TTY_INT, gpd_num, &p_head, &p_tail);
+				ior = (tty_io_request_t *)QBM_DES_GET_SW_CTRL_FIELD(p_head);
+				ior->first_gpd = p_head;
+				ior->last_gpd = p_tail;
+				
+				// Copy data to gpds (the following code only suit for QBM_TYPE_TTY_INT)
+				list_each_gpd(gpd_t, ior->first_gpd, ior->last_gpd) {
+					int copylen = MIN(QBM_TTY_XXX_DATA_LEN, datalen - offset);
+					
+					kal_mem_cpy(QBM_DES_GET_DATAPTR(gpd_t), SendBuff + offset, copylen);
+					offset += copylen;
+					
+					QBM_DES_SET_DATALEN(gpd_t, copylen);
+				}
+				
+				DclSerialPort_UpModuleTransmit(handle, ior);
+			}
+			
+			// Dummy Driver
+			{
+				// Free GPD or Return Tx GPD to Upper Module
+				Tx_Flush_Gpd(device);
+			}
+		} while (offset < datalen);
+		
+		// Compare data with Hardware Buffer
+		for (i = 0; i < datalen; i++) {
+			if (SendBuff[i] ^ Dev_Mgmt[device].HwBuff[i]) {
+				data_corrupt = KAL_TRUE;
+				break;
+			}				
+		}
+	}
+		
+	// Upper Module DeInit & Driver Detatch & DeRegister Callback
+	DataPath_Close(handle);
+	
+	// Check data no corrupt
+	if (data_corrupt) {
+		FAIL_MSG("[NewTxPath] Data Corrupt in Device# = %d, DevType = %d", device, devtype);
+		return KAL_FALSE;
+	}
+	
+	// Check there is no assert
+	if (ut_assert_flag) {
+		ut_assert_flag = KAL_FALSE; // clear flag
+		FAIL_MSG("[NewTxPath] There is a assertion in exception. It's found at Test Case end");
+		return KAL_FALSE;
+	}
+	return KAL_TRUE;
+}
+
+kal_bool NewTxLightPath(kal_char *p_ret_err_str, kal_uint32 *p_ret_err_str_sz)
+{
+	DCL_DEV device;
+	DCL_STATUS status;
+    DCL_HANDLE handle;
+	SIO_TYPE_T devtype;
+	kal_bool data_corrupt;
+
+	// Setup Port & Driver Type
+	device = uart_port1;
+	devtype = DCL_UART_USB_TYPE;		// Driver type is GPD_DRV_TYPE
+	data_corrupt = KAL_FALSE;
+	
+	// Get handle
+	handle = DclSerialPort_Open(device, 0);
+	
+	// Upper Module Initialize & Driver Register callback and then Attach
+	DataPath_Setup(handle, devtype, TTY_FLAG_NEW_TX);
+	
+	// New Tx Path
+	// Send Tx Data -> TxDoneCb(For free gpds)
+	{
+		char SendBuff[UT_TEST_SIZE];
+		int datalen;
+		int offset;
+		int i;
+		
+		// Clear Hardware Buffer
+		Hw_ClearBuff(device);
+		
+		// Prepare Data to Send
+		datalen = UT_TEST_SIZE;
+		for (i = 0; i < datalen; i++) {
+			SendBuff[i] = i & UT_DATA_MASK;
+		}
+		
+		// Setup Tx Buffer Structure
+		offset = 0;
+		
+		// Sending Data Until Sending Complete
+		do {
+			// Dummy Upper Module
+			{
+				void *gpd_t;
+				void *p_head;
+				void *p_tail;
+				tty_io_request_t *ior;
+				int gpd_num = 2;
+				
+				// Create gpds for ior
+				// GPD_TYPE: QBM_TYPE_TTY_INT
+				// GPD_LEN: QBM_TTY_XXX_DATA_LEN(1024)
+				qbmt_alloc_q_no_tail(QBM_TYPE_TTY_INT, gpd_num, &p_head, &p_tail);
+				ior = (tty_io_request_t *)QBM_DES_GET_SW_CTRL_FIELD(p_head);
+				ior->first_gpd = p_head;
+				ior->last_gpd = p_tail;
+				
+				// Copy data to gpds (the following code only suit for QBM_TYPE_TTY_INT)
+				list_each_gpd(gpd_t, ior->first_gpd, ior->last_gpd) {
+					int copylen = MIN(QBM_TTY_XXX_DATA_LEN, datalen - offset);
+					
+					kal_mem_cpy(QBM_DES_GET_DATAPTR(gpd_t), SendBuff + offset, copylen);
+					offset += copylen;
+					
+					QBM_DES_SET_DATALEN(gpd_t, copylen);
+				}
+				
+				DclSerialPort_UpModuleTransmitLight(handle, ior);
+			}
+			
+			// Dummy Driver
+			{
+				// Free GPD or Return Tx GPD to Upper Module
+				Tx_Flush_Gpd(device);
+			}
+		} while (offset < datalen);
+		
+		// Compare data with Hardware Buffer
+		for (i = 0; i < datalen; i++) {
+			if (SendBuff[i] ^ Dev_Mgmt[device].HwBuff[i]) {
+				data_corrupt = KAL_TRUE;
+				break;
+			}				
+		}
+	}
+		
+	// Upper Module DeInit & Driver Detatch & DeRegister Callback
+	DataPath_Close(handle);
+	
+	// Check data no corrupt
+	if (data_corrupt) {
+		FAIL_MSG("[NewTxPath] Data Corrupt in Device# = %d, DevType = %d", device, devtype);
+		return KAL_FALSE;
+	}
+	
+	// Check there is no assert
+	if (ut_assert_flag) {
+		ut_assert_flag = KAL_FALSE; // clear flag
+		FAIL_MSG("[NewTxPath] There is a assertion in exception. It's found at Test Case end");
+		return KAL_FALSE;
+	}
+	return KAL_TRUE;
+}
+
+kal_bool NewRxPath(kal_char *p_ret_err_str, kal_uint32 *p_ret_err_str_sz)
+{
+	DCL_DEV device;
+	DCL_STATUS status;
+    DCL_HANDLE handle;
+	SIO_TYPE_T devtype;
+	kal_bool data_corrupt;
+
+	// Setup Port & Driver Type
+	device = uart_port1;
+	devtype = DCL_UART_USB_TYPE;		// Driver type is GPD_DRV_TYPE
+	data_corrupt = KAL_FALSE;
+	
+	// Get handle
+	handle = DclSerialPort_Open(device, 0);
+	
+	// Upper Module Initialize & Driver Register callback and then Attach
+	DataPath_Setup(handle, devtype, TTY_FLAG_NEW_RX);
+
+	// New Rx Path
+	// Send Rx gpds -> RxCb
+	{
+		char RecvBuff[UT_TEST_SIZE];
+		int datalen;
+		int offset;
+		int i;
+		
+		// Clear Hardware Buffer
+		Hw_ClearBuff(device);
+		
+		// Prepare Rx Data
+		datalen = UT_TEST_SIZE;
+		for (i = 0; i < datalen; i++) {
+			Dev_Mgmt[device].HwBuff[i] = i & UT_DATA_MASK;
+		}
+		Dev_Mgmt[device].size = datalen;
+		
+		// Setup Rx Buffer Structure
+		offset = 0;
+		
+		
+		
+		// Receiving Data Until Data empty in Hardware
+		do {
+			// Dummy Upper Module
+			{
+				void *p_head;
+				void *p_tail;
+				tty_io_request_t *ior;
+				int gpd_num = 2;
+				
+				// Create gpds for ior
+				// GPD_TYPE: QBM_TYPE_TTY_INT
+				// GPD_LEN: QBM_TTY_XXX_DATA_LEN(1024)
+				qbmt_alloc_q(QBM_TYPE_TTY_INT, gpd_num, &p_head, &p_tail);
+				ior = (tty_io_request_t *)QBM_DES_GET_SW_CTRL_FIELD(p_head);
+				ior->first_gpd = p_head;
+				ior->last_gpd = p_tail;
+				
+				// Send Rx_Ior to Driver
+				DclSerialPort_UpModuleAssignRxIor(handle, ior);
+			}
+			
+			// Dummy Hardware Operation
+			{
+				// Copy Data to Driver Rx GPD in the Rx Queue
+				Hw_PopDataToRxQue(device);
+			}
+			
+			// Dummy Driver 
+			{
+				// Get Rx GPDs(Contain Received Data) by De-Q
+				void * ior = Rx_DeQueToIor(device);
+				// Rx callback to send ior to tty
+				DclSerialPort_DrvRx(handle, DRV_TTY_UT, ior);
+			}
+			
+			// Dummy Upper Module
+			{
+				if (Dev_Mgmt[device].Rx_Ior) {
+					void *gpd_t;
+				
+					// Copy data from gpds (the following code only suit for QBM_TYPE_TTY_INT)
+					list_each_gpd(gpd_t, Dev_Mgmt[device].Rx_Ior->first_gpd, Dev_Mgmt[device].Rx_Ior->last_gpd) {
+						int copylen = MIN(QBM_TTY_XXX_DATA_LEN, QBM_DES_GET_DATALEN(gpd_t));
+						
+						kal_mem_cpy(RecvBuff + offset, QBM_DES_GET_DATAPTR(gpd_t), copylen);
+						offset += copylen;
+					}
+					// Free Rx Ior
+					qbmt_dest_q(Dev_Mgmt[device].Rx_Ior->first_gpd, Dev_Mgmt[device].Rx_Ior->last_gpd);
+				}
+			}
+		} while (offset < datalen);
+		
+		// Compare data with Hardware Buffer
+		for (i = 0; i < datalen; i++) {
+			if (RecvBuff[i] ^ Dev_Mgmt[device].HwBuff[i]) {
+				data_corrupt = KAL_TRUE;
+				break;
+			}				
+		}
+	}
+		
+	// Upper Module DeInit & Driver Detatch & DeRegister Callback
+	DataPath_Close(handle);
+	
+	// Check data no corrupt
+	if (data_corrupt) {
+		FAIL_MSG("[NewRxPath] Data Corrupt in Device# = %d, DevType = %d", device, devtype);
+		return KAL_FALSE;
+	}	
+	
+	// Check there is no assert
+	if (ut_assert_flag) {
+		ut_assert_flag = KAL_FALSE; // clear flag
+		FAIL_MSG("[NewRxPath] There is a assertion in exception. It's found at Test Case end");
+		return KAL_FALSE;
+	}
+	return KAL_TRUE;
+}
+
+kal_bool BuffModTxPath(kal_char *p_ret_err_str, kal_uint32 *p_ret_err_str_sz)
+{
+	DCL_DEV device;
+	DCL_STATUS status;
+    DCL_HANDLE handle;
+	SIO_TYPE_T devtype;
+	kal_bool data_corrupt;
+
+	// Setup Port & Driver Type
+	device = uart_port1;
+	devtype = DCL_UART_CMUX_TYPE;		// Driver type is BUFF_DRV_TYPE
+	data_corrupt = KAL_FALSE;
+	
+	// Get handle
+	handle = DclSerialPort_Open(device, 0);
+	
+	// Upper Module Initialize & Driver Register callback and then Attach
+	DataPath_Setup(handle, devtype, 0);
+
+	// Conventional Tx Path
+	// Send Tx Data -> TxDoneCb -> Get "Ready to Write" ilm
+	{
+		UART_CTRL_PUT_BYTES_T ur_ctrl_putbytes;
+		char SendBuff[UT_TEST_SIZE];
+		int datalen;
+		int offset;
+		int i;
+		
+		// Clear Hardware Buffer
+		Hw_ClearBuff(device);
+		
+		// Prepare Data to Send
+		datalen = UT_TEST_SIZE;
+		for (i = 0; i < datalen; i++) {
+			SendBuff[i] = i & UT_DATA_MASK;
+		}
+		
+		
+		// Setup Tx Buffer Structure
+		offset = 0;
+		ur_ctrl_putbytes.u4OwenrId = MOD_TTY_UT;
+		ur_ctrl_putbytes.puBuffaddr = SendBuff;
+		ur_ctrl_putbytes.u2Length = datalen;
+		
+		// Sending Data Until Sending Complete
+		do {
+			// Dummy Upper Module
+			{
+				DclSerialPort_Control(handle, SIO_CMD_PUT_BYTES, (DCL_CTRL_DATA_T*) &ur_ctrl_putbytes);
+				offset += ur_ctrl_putbytes.u2RetSize;
+				
+				// Update Tx Buffer Structure
+				ur_ctrl_putbytes.puBuffaddr = SendBuff + offset;
+				ur_ctrl_putbytes.u2Length = datalen - offset;
+			}
+			
+			// Dummy Driver
+			{
+				// Using TxDoneCb to inform TTYCore
+				DclSerialPort_DrvTxDone(handle, DRV_TTY_UT, NULL);
+			}
+
+			// Dummy Upper Module
+			{
+				// In conventional path, _tty_tx_done_cb will send ilm to inform upper module.
+				// when data buffer have the remaining data still haven't be sent.
+				if (offset < datalen) {
+					ilm_struct current_ilm;
+				
+					msg_receive_extq(&current_ilm);
+					if (current_ilm.msg_id != MSG_ID_UART_READY_TO_WRITE_IND) {
+						destroy_ilm(&current_ilm);
+						return KAL_FALSE;
+					}
+					destroy_ilm(&current_ilm);
+				}
+			}
+		} while (offset < datalen);
+		
+		// Compare data with Hardware Buffer
+		for (i = 0; i < datalen; i++) {
+			if (SendBuff[i] ^ Dev_Mgmt[device].HwBuff[i]) {
+				data_corrupt = KAL_TRUE;
+				break;
+			}				
+		}
+	}
+		
+	// Upper Module DeInit & Driver Detatch & DeRegister Callback
+	DataPath_Close(handle);
+	
+	// Check data no corrupt
+	if (data_corrupt) {
+		FAIL_MSG("[BuffModTxPath] Data Corrupt in Device# = %d, DevType = %d", device, devtype);
+		return KAL_FALSE;
+	}	
+	
+	// Check there is no assert
+	if (ut_assert_flag) {
+		ut_assert_flag = KAL_FALSE; // clear flag
+		FAIL_MSG("[BuffModTxPath] There is a assertion in exception. It's found at Test Case end");
+		return KAL_FALSE;
+	}
+	return KAL_TRUE;
+}
+
+kal_bool BuffModRxPath(kal_char *p_ret_err_str, kal_uint32 *p_ret_err_str_sz)
+{
+	DCL_DEV device;
+	DCL_STATUS status;
+    DCL_HANDLE handle;
+	SIO_TYPE_T devtype;
+	kal_bool data_corrupt;
+
+	// Setup Port & Driver Type
+	device = uart_port1;
+	devtype = DCL_UART_CMUX_TYPE;		// Driver type is BUFF_DRV_TYPE
+	data_corrupt = KAL_FALSE;
+	
+	// Get handle
+	handle = DclSerialPort_Open(device, 0);
+	
+	// Upper Module Initialize & Driver Register callback and then Attach
+	DataPath_Setup(handle, devtype, 0);
+
+	// Conventional Rx Path
+	// Prepare Rx Data -> RxCb -> Get "Ready to Read" ilm -> Get Rx Data
+	{
+		UART_CTRL_GET_BYTES_T ur_ctrl_getbytes;
+		char RecvBuff[UT_TEST_SIZE];
+		int datalen;
+		int offset;
+		int i;
+		
+		// Clear Hardware Buffer
+		Hw_ClearBuff(device);
+		
+		// Prepare Rx Data
+		datalen = UT_TEST_SIZE;
+		for (i = 0; i < datalen; i++) {
+			Dev_Mgmt[device].HwBuff[i] = i & UT_DATA_MASK;
+		}
+		Dev_Mgmt[device].size = datalen;
+		
+		// Setup Rx Buffer Structure
+		offset = 0;
+		ur_ctrl_getbytes.u4OwenrId = MOD_TTY_UT;
+		ur_ctrl_getbytes.puBuffaddr = RecvBuff;
+		ur_ctrl_getbytes.u2Length = datalen;
+			
+		
+		// Dummy Driver 
+		{
+			// Using RxCb to inform TTYCore
+			DclSerialPort_DrvRx(handle, DRV_TTY_UT, NULL);
+			
+			// It will raise the flag rx_up_mod_wait at Rx buffer mode initial 
+			// When using Rx_Cb to inform TTYCore it will send ilm at first time.
+			{
+				ilm_struct current_ilm;
+			
+				msg_receive_extq(&current_ilm);
+				if (current_ilm.msg_id != MSG_ID_UART_READY_TO_READ_IND) {
+					destroy_ilm(&current_ilm);
+					return KAL_FALSE;
+				}
+				destroy_ilm(&current_ilm);
+			}
+		}
+		do {						
+			// Dummy Upper Module
+			{
+				// Get Data
+				DclSerialPort_Control(handle, SIO_CMD_GET_BYTES, (DCL_CTRL_DATA_T*) &ur_ctrl_getbytes);
+				offset += ur_ctrl_getbytes.u2RetSize;
+				
+				// Update Rx Buffer Structure 
+				ur_ctrl_getbytes.puBuffaddr = RecvBuff + offset;
+				ur_ctrl_getbytes.u2Length = datalen - offset;
+			}
+			
+			///TODO: check there is no ilm because there is sent in SIO_CMD_GET_RX_AVAIL
+		} while (Dev_Mgmt[device].size);
+		
+		// Compare data with Hardware Buffer
+		for (i = 0; i < datalen; i++) {
+			if (RecvBuff[i] ^ Dev_Mgmt[device].HwBuff[i]) {
+				data_corrupt = KAL_TRUE;
+				break;
+			}				
+		}
+	}
+		
+	// Upper Module DeInit & Driver Detatch & DeRegister Callback
+	DataPath_Close(handle);
+	
+	// Check data no corrupt
+	if (data_corrupt) {
+		FAIL_MSG("[BuffModRxPath] Data Corrupt in Device# = %d, DevType = %d", device, devtype);
+		return KAL_FALSE;
+	}
+	
+	// Check there is no assert
+	if (ut_assert_flag) {
+		ut_assert_flag = KAL_FALSE; // clear flag
+		FAIL_MSG("[BuffModRxPath] There is a assertion in exception. It's found at Test Case end");
+		return KAL_FALSE;
+	}
+	return KAL_TRUE;
+}
+
+// Loopback Test Sub-Case
+kal_bool NewTx_NewRx(kal_char *p_ret_err_str, kal_uint32 *p_ret_err_str_sz)
+{
+	DCL_DEV device;
+	DCL_STATUS status;
+    DCL_HANDLE handle;
+	SIO_TYPE_T devtype;
+	kal_bool data_corrupt;
+
+	// Setup Port & Driver Type
+	device = uart_port1;
+	devtype = DCL_UART_USB_TYPE;		// Driver type is GPD_DRV_TYPE
+	data_corrupt = KAL_FALSE;
+	
+	// Get handle
+	handle = DclSerialPort_Open(device, 0);
+
+	// Upper Module Initialize & Driver Register callback and then Attach
+	DataPath_Setup(handle, devtype, TTY_FLAG_NEW_TX | TTY_FLAG_NEW_RX);
+	
+	// Send Tx Data -> TxDoneCb(For free gpds) -> Send Rx gpds -> RxCb
+	{
+		char SendBuff[UT_TEST_SIZE];
+		char RecvBuff[UT_TEST_SIZE];
+		int datalen;
+		int s_offset;
+		int r_offset;
+		int i;
+		
+		// Clear Hardware Buffer
+		Hw_ClearBuff(device);
+		
+		// Prepare Data to Send
+		datalen = UT_TEST_SIZE;
+		for (i = 0; i < datalen; i++) {
+			SendBuff[i] = i & UT_DATA_MASK;
+		}
+		
+		// Setup Buffer Structure
+		s_offset = 0;
+		r_offset = 0;
+		
+		// Sending Data Until Sending Complete
+		do {
+			// Dummy Upper Module
+			{
+				void *gpd_t;
+				void *p_head;
+				void *p_tail;
+				tty_io_request_t *ior;
+				int gpd_num = 2;
+				
+				// Create gpds for ior
+				// GPD_TYPE: QBM_TYPE_TTY_INT
+				// GPD_LEN: QBM_TTY_XXX_DATA_LEN(1024)
+				qbmt_alloc_q_no_tail(QBM_TYPE_TTY_INT, gpd_num, &p_head, &p_tail);
+				ior = (tty_io_request_t *)QBM_DES_GET_SW_CTRL_FIELD(p_head);
+				ior->first_gpd = p_head;
+				ior->last_gpd = p_tail;
+				
+				// Copy data to gpds (the following code only suit for QBM_TYPE_TTY_INT)
+				list_each_gpd(gpd_t, ior->first_gpd, ior->last_gpd) {
+					int copylen = MIN(QBM_TTY_XXX_DATA_LEN, datalen - s_offset);
+					
+					kal_mem_cpy(QBM_DES_GET_DATAPTR(gpd_t), SendBuff + s_offset, copylen);
+					s_offset += copylen;
+					
+					QBM_DES_SET_DATALEN(gpd_t, copylen);
+				}
+				
+				DclSerialPort_UpModuleTransmit(handle, ior);
+			}
+			
+			// Dummy Driver
+			{
+				// Free GPD or Return Tx GPD to Upper Module
+				Tx_Flush_Gpd(device);
+			}
+		} while (s_offset < datalen);
+		
+		// Receiving Data Until Data empty in Hardware
+		do {
+			// Dummy Upper Module
+			{
+				void *p_head;
+				void *p_tail;
+				tty_io_request_t *ior;
+				int gpd_num = 2;
+				
+				// Create gpds for ior
+				// GPD_TYPE: QBM_TYPE_TTY_INT
+				// GPD_LEN: QBM_TTY_XXX_DATA_LEN(1024)
+				qbmt_alloc_q(QBM_TYPE_TTY_INT, gpd_num, &p_head, &p_tail);
+				ior = (tty_io_request_t *)QBM_DES_GET_SW_CTRL_FIELD(p_head);
+				ior->first_gpd = p_head;
+				ior->last_gpd = p_tail;
+				
+				// Send Rx_Ior to Driver
+				DclSerialPort_UpModuleAssignRxIor(handle, ior);
+			}
+			
+			// Dummy Hardware Operation
+			{
+				// Copy Data to Driver Rx GPD in the Rx Queue
+				Hw_PopDataToRxQue(device);
+			}
+			
+			// Dummy Driver 
+			{
+				// Get Rx GPDs(Contain Received Data) by De-Q
+				void * ior = Rx_DeQueToIor(device);
+				// Rx callback to send ior to tty
+				DclSerialPort_DrvRx(handle, DRV_TTY_UT, ior);
+			}
+			
+			// Dummy Upper Module
+			{
+				if (Dev_Mgmt[device].Rx_Ior) {
+					void *gpd_t;
+				
+					// Copy data from gpds (the following code only suit for QBM_TYPE_TTY_INT)
+					list_each_gpd(gpd_t, Dev_Mgmt[device].Rx_Ior->first_gpd, Dev_Mgmt[device].Rx_Ior->last_gpd) {
+						int copylen = MIN(QBM_TTY_XXX_DATA_LEN, QBM_DES_GET_DATALEN(gpd_t));
+						
+						kal_mem_cpy(RecvBuff + r_offset, QBM_DES_GET_DATAPTR(gpd_t), copylen);
+						r_offset += copylen;
+					}
+					// Free Rx Ior
+					qbmt_dest_q(Dev_Mgmt[device].Rx_Ior->first_gpd, Dev_Mgmt[device].Rx_Ior->last_gpd);
+				}
+			}
+		} while (r_offset < datalen);
+		
+		// Compare data between Send Buffer & Receive Buffer
+		for (i = 0; i < datalen; i++) {
+			if (SendBuff[i] ^ RecvBuff[i]) {
+				data_corrupt = KAL_TRUE;
+				break;
+			}				
+		}
+	}
+		
+	// Upper Module DeInit & Driver Detatch & DeRegister Callback
+	DataPath_Close(handle);
+	
+	// Check data no corrupt
+	if (data_corrupt) {
+		FAIL_MSG("Data Corrupt in Device# = %d, DevType = %d", device, devtype);
+		return KAL_FALSE;
+	}
+	
+	// Check there is no assert
+	if (ut_assert_flag) {
+		ut_assert_flag = KAL_FALSE; // clear flag
+		FAIL_MSG("There is a assertion in exception. It's found at Test Case end");
+		return KAL_FALSE;
+	}
+	return KAL_TRUE;
+}
+
+kal_bool NewTx_ConvRx(kal_char *p_ret_err_str, kal_uint32 *p_ret_err_str_sz)
+{
+	DCL_DEV device;
+	DCL_STATUS status;
+    DCL_HANDLE handle;
+	SIO_TYPE_T devtype;
+	kal_bool data_corrupt;
+
+	// Setup Port & Driver Type
+	device = uart_port1;
+	devtype = DCL_UART_USB_TYPE;		// Driver type is GPD_DRV_TYPE
+	data_corrupt = KAL_FALSE;
+	
+	// Get handle
+	handle = DclSerialPort_Open(device, 0);
+	
+	// Upper Module Initialize & Driver Register callback and then Attach
+	DataPath_Setup(handle, devtype, TTY_FLAG_NEW_TX);
+	
+	// Send Tx Data -> TxDoneCb(For free gpds) -> RxCb -> Send Rx Buffer 
+	{
+		UART_CTRL_GET_BYTES_T ur_ctrl_getbytes;
+		char SendBuff[UT_TEST_SIZE];
+		char RecvBuff[UT_TEST_SIZE];
+		int datalen;
+		int s_offset;
+		int r_offset;
+		int i;
+		
+		// Clear Hardware Buffer
+		Hw_ClearBuff(device);
+		
+		// Prepare Data to Send
+		datalen = UT_TEST_SIZE;
+		for (i = 0; i < datalen; i++) {
+			SendBuff[i] = i & UT_DATA_MASK;
+		}
+		
+		// Setup Tx Buffer Structure
+		s_offset = 0;
+		r_offset = 0;
+		ur_ctrl_getbytes.u4OwenrId = MOD_TTY_UT;
+		ur_ctrl_getbytes.puBuffaddr = RecvBuff;
+		ur_ctrl_getbytes.u2Length = datalen;
+		
+		// Sending Data Until Sending Complete
+		do {
+			// Dummy Upper Module
+			{
+				void *gpd_t;
+				void *p_head;
+				void *p_tail;
+				tty_io_request_t *ior;
+				int gpd_num = 2;
+				
+				// Create gpds for ior
+				// GPD_TYPE: QBM_TYPE_TTY_INT
+				// GPD_LEN: QBM_TTY_XXX_DATA_LEN(1024)
+				qbmt_alloc_q_no_tail(QBM_TYPE_TTY_INT, gpd_num, &p_head, &p_tail);
+				ior = (tty_io_request_t *)QBM_DES_GET_SW_CTRL_FIELD(p_head);
+				ior->first_gpd = p_head;
+				ior->last_gpd = p_tail;
+				
+				// Copy data to gpds (the following code only suit for QBM_TYPE_TTY_INT)
+				list_each_gpd(gpd_t, ior->first_gpd, ior->last_gpd) {
+					int copylen = MIN(QBM_TTY_XXX_DATA_LEN, datalen - s_offset);
+					
+					kal_mem_cpy(QBM_DES_GET_DATAPTR(gpd_t), SendBuff + s_offset, copylen);
+					s_offset += copylen;
+					
+					QBM_DES_SET_DATALEN(gpd_t, copylen);
+				}
+				
+				DclSerialPort_UpModuleTransmit(handle, ior);
+			}
+			
+			// Dummy Driver
+			{
+				// Free GPD or Return Tx GPD to Upper Module
+				Tx_Flush_Gpd(device);
+			}
+		} while (s_offset < datalen);
+		
+		// Receiving Data Until Data empty in Hardware
+		do {
+			// Dummy Hardware Operation
+			{
+				// Copy Data to Driver Rx GPD in the Rx Queue
+				Hw_PopDataToRxQue(device);
+			}
+			
+			// Dummy Driver 
+			{
+				// Get Rx GPDs(Contain Received Data) by De-Q
+				void * ior = Rx_DeQueToIor(device);
+				// Rx callback to send ior to tty
+				if (ior) {
+					DclSerialPort_DrvRx(handle, DRV_TTY_UT, ior);
+				}
+			}
+						
+			// Dummy Upper Module
+			{
+				// In conventional path, _tty_rx_cb will send ilm to inform upper module data ready to read.
+				{
+					ilm_struct current_ilm;
+				
+					msg_receive_extq(&current_ilm);
+					if (current_ilm.msg_id != MSG_ID_UART_READY_TO_READ_IND) {
+						destroy_ilm(&current_ilm);
+						return KAL_FALSE;
+					}
+					destroy_ilm(&current_ilm);
+				}
+				
+				// Get Data
+				DclSerialPort_Control(handle, SIO_CMD_GET_BYTES, (DCL_CTRL_DATA_T*) &ur_ctrl_getbytes);
+				r_offset += ur_ctrl_getbytes.u2RetSize;
+				
+				// Update Rx Buffer Structure 
+				ur_ctrl_getbytes.puBuffaddr = RecvBuff + r_offset;
+				ur_ctrl_getbytes.u2Length = datalen - r_offset;
+			}
+		} while (Dev_Mgmt[device].size);
+		
+		// Compare data between Send Buffer & Receive Buffer
+		for (i = 0; i < datalen; i++) {
+			if (SendBuff[i] ^ RecvBuff[i]) {
+				data_corrupt = KAL_TRUE;
+				break;
+			}				
+		}
+	}
+		
+	// Upper Module DeInit & Driver Detatch & DeRegister Callback
+	DataPath_Close(handle);
+	
+	// Check data no corrupt
+	if (data_corrupt) {
+		FAIL_MSG("Data Corrupt in Device# = %d, DevType = %d", device, devtype);
+		return KAL_FALSE;
+	}
+	
+	// Check there is no assert
+	if (ut_assert_flag) {
+		ut_assert_flag = KAL_FALSE; // clear flag
+		FAIL_MSG("There is a assertion in exception. It's found at Test Case end");
+		return KAL_FALSE;
+	}
+	return KAL_TRUE;
+}
+
+kal_bool ConvTx_NewRx(kal_char *p_ret_err_str, kal_uint32 *p_ret_err_str_sz)
+{
+	DCL_DEV device;
+	DCL_STATUS status;
+    DCL_HANDLE handle;
+	SIO_TYPE_T devtype;
+	kal_bool data_corrupt;
+
+	// Setup Port & Driver Type
+	device = uart_port1;
+	devtype = DCL_UART_USB_TYPE;		// Driver type is GPD_DRV_TYPE
+	data_corrupt = KAL_FALSE;
+	
+	// Get handle
+	handle = DclSerialPort_Open(device, 0);
+	
+	// Upper Module Initialize & Driver Register callback and then Attach
+	DataPath_Setup(handle, devtype, TTY_FLAG_NEW_RX);
+	
+	// Send Tx Data -> TxDoneCb -> Get "Ready to Write" ilm -> Send Rx gpds -> RxCb  
+	{
+		UART_CTRL_PUT_BYTES_T ur_ctrl_putbytes;
+		char SendBuff[UT_TEST_SIZE];
+		char RecvBuff[UT_TEST_SIZE];
+		int datalen;
+		int s_offset;
+		int r_offset;
+		int i;
+		
+		// Clear Hardware Buffer
+		Hw_ClearBuff(device);
+		
+		// Prepare Data to Send
+		datalen = UT_TEST_SIZE;
+		for (i = 0; i < datalen; i++) {
+			SendBuff[i] = i & UT_DATA_MASK;
+		}
+		
+		// Setup Buffer Structure
+		s_offset = 0;
+		ur_ctrl_putbytes.u4OwenrId = MOD_TTY_UT;
+		ur_ctrl_putbytes.puBuffaddr = SendBuff;
+		ur_ctrl_putbytes.u2Length = datalen;
+		r_offset = 0;
+		
+		// Sending Data Until Sending Complete
+		do {
+			// Dummy Upper Module
+			{
+				DclSerialPort_Control(handle, SIO_CMD_PUT_BYTES, (DCL_CTRL_DATA_T*) &ur_ctrl_putbytes);
+				s_offset += ur_ctrl_putbytes.u2RetSize;
+				
+				// Update Tx Buffer Structure
+				ur_ctrl_putbytes.puBuffaddr = SendBuff + s_offset;
+				ur_ctrl_putbytes.u2Length = datalen - s_offset;
+			}
+			
+			// Dummy Driver
+			{
+				// Return Tx GPD to TTYCore
+				Tx_Flush_Gpd(device);
+			}
+			
+			// Dummy Upper Module
+			{
+				// In conventional path, _tty_tx_done_cb will send ilm to inform upper module.
+				// when data buffer have the remaining data still haven't be sent.
+				if (s_offset < datalen) {
+					ilm_struct current_ilm;
+				
+					msg_receive_extq(&current_ilm);
+					if (current_ilm.msg_id != MSG_ID_UART_READY_TO_WRITE_IND) {
+						destroy_ilm(&current_ilm);
+						return KAL_FALSE;
+					}
+					destroy_ilm(&current_ilm);
+				}
+			}
+		} while (s_offset < datalen);
+		
+		// Receiving Data Until Data empty in Hardware
+		do {
+			// Dummy Upper Module
+			{
+				void *p_head;
+				void *p_tail;
+				tty_io_request_t *ior;
+				int gpd_num = 2;
+				
+				// Create gpds for ior
+				// GPD_TYPE: QBM_TYPE_TTY_INT
+				// GPD_LEN: QBM_TTY_XXX_DATA_LEN(1024)
+				qbmt_alloc_q(QBM_TYPE_TTY_INT, gpd_num, &p_head, &p_tail);
+				ior = (tty_io_request_t *)QBM_DES_GET_SW_CTRL_FIELD(p_head);
+				ior->first_gpd = p_head;
+				ior->last_gpd = p_tail;
+				
+				// Send Rx_Ior to Driver
+				DclSerialPort_UpModuleAssignRxIor(handle, ior);
+			}
+			
+			// Dummy Hardware Operation
+			{
+				// Copy Data to Driver Rx GPD in the Rx Queue
+				Hw_PopDataToRxQue(device);
+			}
+			
+			// Dummy Driver 
+			{
+				// Get Rx GPDs(Contain Received Data) by De-Q
+				void * ior = Rx_DeQueToIor(device);
+				// Rx callback to send ior to tty
+				DclSerialPort_DrvRx(handle, DRV_TTY_UT, ior);
+			}
+			
+			// Dummy Upper Module
+			{
+				if (Dev_Mgmt[device].Rx_Ior) {
+					void *gpd_t;
+				
+					// Copy data from gpds (the following code only suit for QBM_TYPE_TTY_INT)
+					list_each_gpd(gpd_t, Dev_Mgmt[device].Rx_Ior->first_gpd, Dev_Mgmt[device].Rx_Ior->last_gpd) {
+						int copylen = MIN(QBM_TTY_XXX_DATA_LEN, QBM_DES_GET_DATALEN(gpd_t));
+						
+						kal_mem_cpy(RecvBuff + r_offset, QBM_DES_GET_DATAPTR(gpd_t), copylen);
+						r_offset += copylen;
+					}
+					// Free Rx Ior
+					qbmt_dest_q(Dev_Mgmt[device].Rx_Ior->first_gpd, Dev_Mgmt[device].Rx_Ior->last_gpd);
+				}
+			}
+		} while (r_offset < datalen);
+		
+		// Compare data between Send Buffer & Receive Buffer
+		for (i = 0; i < datalen; i++) {
+			if (SendBuff[i] ^ RecvBuff[i]) {
+				data_corrupt = KAL_TRUE;
+				break;
+			}				
+		}
+	}
+		
+	// Upper Module DeInit & Driver Detatch & DeRegister Callback
+	DataPath_Close(handle);
+	
+	// Check data no corrupt
+	if (data_corrupt) {
+		FAIL_MSG("Data Corrupt in Device# = %d, DevType = %d", device, devtype);
+		return KAL_FALSE;
+	}
+	
+	// Check there is no assert
+	if (ut_assert_flag) {
+		ut_assert_flag = KAL_FALSE; // clear flag
+		FAIL_MSG("There is a assertion in exception. It's found at Test Case end");
+		return KAL_FALSE;
+	}
+	return KAL_TRUE;
+}
+
+kal_bool ConvTx_ConvRx(kal_char *p_ret_err_str, kal_uint32 *p_ret_err_str_sz)
+{
+	DCL_DEV device;
+	DCL_STATUS status;
+    DCL_HANDLE handle;
+	SIO_TYPE_T devtype;
+	kal_bool data_corrupt;
+
+	// Setup Port & Driver Type
+	device = uart_port1;
+	devtype = DCL_UART_USB_TYPE;		// Driver type is GPD_DRV_TYPE
+	data_corrupt = KAL_FALSE;
+	
+	// Get handle
+	handle = DclSerialPort_Open(device, 0);
+	
+	// Upper Module Initialize & Driver Register callback and then Attach
+	DataPath_Setup(handle, devtype, 0);
+	
+	// if Upper Module is conventional & not buffer mode, driver will using ilm to inform upper module driver attach.
+	{
+		ilm_struct current_ilm;
+
+		msg_receive_extq(&current_ilm);
+		if (current_ilm.msg_id != MSG_ID_UART_PLUGIN_IND) {
+			destroy_ilm(&current_ilm);
+			return KAL_FALSE;
+		}
+		destroy_ilm(&current_ilm);
+	}
+	
+	// Send Tx Data -> TxDoneCb -> Get "Ready to Write" ilm -> RxCb -> Send Rx gpds 
+	{
+		UART_CTRL_PUT_BYTES_T ur_ctrl_putbytes;
+		UART_CTRL_GET_BYTES_T ur_ctrl_getbytes;
+		char SendBuff[UT_TEST_SIZE];
+		char RecvBuff[UT_TEST_SIZE];
+		int datalen;
+		int s_offset;
+		int r_offset;
+		int i;
+		
+		// Clear Hardware Buffer
+		Hw_ClearBuff(device);
+		
+		// Prepare Data to Send
+		datalen = UT_TEST_SIZE;
+		for (i = 0; i < datalen; i++) {
+			SendBuff[i] = i & UT_DATA_MASK;
+		}
+		
+		// Setup Buffer Structure
+		s_offset = 0;
+		ur_ctrl_putbytes.u4OwenrId = MOD_TTY_UT;
+		ur_ctrl_putbytes.puBuffaddr = SendBuff;
+		ur_ctrl_putbytes.u2Length = datalen;
+		r_offset = 0;
+		ur_ctrl_getbytes.u4OwenrId = MOD_TTY_UT;
+		ur_ctrl_getbytes.puBuffaddr = RecvBuff;
+		ur_ctrl_getbytes.u2Length = datalen;
+		
+		// Sending Data Until Sending Complete
+		do {
+			// Dummy Upper Module
+			{
+				DclSerialPort_Control(handle, SIO_CMD_PUT_BYTES, (DCL_CTRL_DATA_T*) &ur_ctrl_putbytes);
+				s_offset += ur_ctrl_putbytes.u2RetSize;
+				
+				// Update Tx Buffer Structure
+				ur_ctrl_putbytes.puBuffaddr = SendBuff + s_offset;
+				ur_ctrl_putbytes.u2Length = datalen - s_offset;
+			}
+			
+			// Dummy Driver
+			{
+				// Return Tx GPD to TTYCore
+				Tx_Flush_Gpd(device);
+			}
+			
+			// Dummy Upper Module
+			{
+				// In conventional path, _tty_tx_done_cb will send ilm to inform upper module.
+				// when data buffer have the remaining data still haven't be sent.
+				if (s_offset < datalen) {
+					ilm_struct current_ilm;
+				
+					msg_receive_extq(&current_ilm);
+					if (current_ilm.msg_id != MSG_ID_UART_READY_TO_WRITE_IND) {
+						destroy_ilm(&current_ilm);
+						return KAL_FALSE;
+					}
+					destroy_ilm(&current_ilm);
+				}
+			}
+		} while (s_offset < datalen);
+		
+		// Receiving Data Until Data empty in Hardware
+		do {
+			// Dummy Hardware Operation
+			{
+				// Copy Data to Driver Rx GPD in the Rx Queue
+				Hw_PopDataToRxQue(device);
+			}
+			
+			// Dummy Driver 
+			{
+				// Get Rx GPDs(Contain Received Data) by De-Q
+				void * ior = Rx_DeQueToIor(device);
+				// Rx callback to send ior to tty
+				if (ior) {
+					DclSerialPort_DrvRx(handle, DRV_TTY_UT, ior);
+				}
+			}
+						
+			// Dummy Upper Module
+			{
+				// In conventional path, _tty_rx_cb will send ilm to inform upper module data ready to read.
+				{
+					ilm_struct current_ilm;
+				
+					msg_receive_extq(&current_ilm);
+					if (current_ilm.msg_id != MSG_ID_UART_READY_TO_READ_IND) {
+						destroy_ilm(&current_ilm);
+						return KAL_FALSE;
+					}
+					destroy_ilm(&current_ilm);
+				}
+				
+				// Get Data
+				DclSerialPort_Control(handle, SIO_CMD_GET_BYTES, (DCL_CTRL_DATA_T*) &ur_ctrl_getbytes);
+				r_offset += ur_ctrl_getbytes.u2RetSize;
+				
+				// Update Rx Buffer Structure 
+				ur_ctrl_getbytes.puBuffaddr = RecvBuff + r_offset;
+				ur_ctrl_getbytes.u2Length = datalen - r_offset;
+			}
+		} while (Dev_Mgmt[device].size);
+		
+		// Compare data between Send Buffer & Receive Buffer
+		for (i = 0; i < datalen; i++) {
+			if (SendBuff[i] ^ RecvBuff[i]) {
+				data_corrupt = KAL_TRUE;
+				break;
+			}				
+		}
+	}
+		
+	// Upper Module DeInit & Driver Detatch & DeRegister Callback
+	DataPath_Close(handle);
+	
+	// Check data no corrupt
+	if (data_corrupt) {
+		FAIL_MSG("Data Corrupt in Device# = %d, DevType = %d", device, devtype);
+		return KAL_FALSE;
+	}
+	
+	// Check there is no assert
+	if (ut_assert_flag) {
+		ut_assert_flag = KAL_FALSE; // clear flag
+		FAIL_MSG("There is a assertion in exception. It's found at Test Case end");
+		return KAL_FALSE;
+	}
+	return KAL_TRUE;
+}
+
+kal_bool BuffMod_ConvTx_ConvRx(kal_char *p_ret_err_str, kal_uint32 *p_ret_err_str_sz)
+{
+	DCL_DEV device;
+	DCL_STATUS status;
+    DCL_HANDLE handle;
+	SIO_TYPE_T devtype;
+	kal_bool data_corrupt;
+
+	// Setup Port & Driver Type
+	device = uart_port1;
+	devtype = DCL_UART_CMUX_TYPE;		// Driver type is BUFF_DRV_TYPE
+	data_corrupt = KAL_FALSE;
+	
+	// Get handle
+	handle = DclSerialPort_Open(device, 0);
+	
+	// Upper Module Initialize & Driver Register callback and then Attach
+	DataPath_Setup(handle, devtype, 0);
+	
+	// Send Tx Data -> TxDoneCb -> Get "Ready to Write" ilm -> RxCb -> Send Rx gpds 
+	{
+		UART_CTRL_PUT_BYTES_T ur_ctrl_putbytes;
+		UART_CTRL_GET_BYTES_T ur_ctrl_getbytes;
+		char SendBuff[UT_TEST_SIZE];
+		char RecvBuff[UT_TEST_SIZE];
+		int datalen;
+		int s_offset;
+		int r_offset;
+		int i;
+		
+		// Clear Hardware Buffer
+		Hw_ClearBuff(device);
+		
+		// Prepare Data to Send
+		datalen = UT_TEST_SIZE;
+		for (i = 0; i < datalen; i++) {
+			SendBuff[i] = i & UT_DATA_MASK;
+		}
+		
+		// Setup Buffer Structure
+		s_offset = 0;
+		ur_ctrl_putbytes.u4OwenrId = MOD_TTY_UT;
+		ur_ctrl_putbytes.puBuffaddr = SendBuff;
+		ur_ctrl_putbytes.u2Length = datalen;
+		r_offset = 0;
+		ur_ctrl_getbytes.u4OwenrId = MOD_TTY_UT;
+		ur_ctrl_getbytes.puBuffaddr = RecvBuff;
+		ur_ctrl_getbytes.u2Length = datalen;
+		
+		// Sending Data Until Sending Complete
+		do {
+			// Dummy Upper Module
+			{
+				DclSerialPort_Control(handle, SIO_CMD_PUT_BYTES, (DCL_CTRL_DATA_T*) &ur_ctrl_putbytes);
+				s_offset += ur_ctrl_putbytes.u2RetSize;
+				
+				// Update Tx Buffer Structure
+				ur_ctrl_putbytes.puBuffaddr = SendBuff + s_offset;
+				ur_ctrl_putbytes.u2Length = datalen - s_offset;
+			}
+			
+			// Dummy Driver
+			{
+				// Using TxDoneCb to inform TTYCore
+				DclSerialPort_DrvTxDone(handle, DRV_TTY_UT, NULL);
+			}
+			
+			// Dummy Upper Module
+			{
+				// In conventional path, _tty_tx_done_cb will send ilm to inform upper module.
+				// when data buffer have the remaining data still haven't be sent.
+				if (s_offset < datalen) {
+					ilm_struct current_ilm;
+				
+					msg_receive_extq(&current_ilm);
+					if (current_ilm.msg_id != MSG_ID_UART_READY_TO_WRITE_IND) {
+						destroy_ilm(&current_ilm);
+						return KAL_FALSE;
+					}
+					destroy_ilm(&current_ilm);
+				}
+			}
+		} while (s_offset < datalen);
+		
+		// Dummy Driver 
+		{
+			// Using RxCb to inform TTYCore
+			DclSerialPort_DrvRx(handle, DRV_TTY_UT, NULL);
+			
+			// It will raise the flag rx_up_mod_wait at Rx buffer mode initial 
+			// When using Rx_Cb to inform TTYCore it will send ilm at first time. 
+			{
+				ilm_struct current_ilm;
+			
+				msg_receive_extq(&current_ilm);
+				if (current_ilm.msg_id != MSG_ID_UART_READY_TO_READ_IND) {
+					destroy_ilm(&current_ilm);
+					return KAL_FALSE;
+				}
+				destroy_ilm(&current_ilm);
+			}
+		}
+		// Receiving Data Until Data empty in Hardware
+		do {	
+			// Dummy Upper Module
+			{
+				// Get Data
+				DclSerialPort_Control(handle, SIO_CMD_GET_BYTES, (DCL_CTRL_DATA_T*) &ur_ctrl_getbytes);
+				r_offset += ur_ctrl_getbytes.u2RetSize;
+				
+				// Update Rx Buffer Structure 
+				ur_ctrl_getbytes.puBuffaddr = RecvBuff + r_offset;
+				ur_ctrl_getbytes.u2Length = datalen - r_offset;
+			}
+		} while (Dev_Mgmt[device].size);
+		
+		// Compare data between Send Buffer & Receive Buffer
+		for (i = 0; i < datalen; i++) {
+			if (SendBuff[i] ^ RecvBuff[i]) {
+				data_corrupt = KAL_TRUE;
+				break;
+			}				
+		}
+	}
+		
+	// Upper Module DeInit & Driver Detatch & DeRegister Callback
+	DataPath_Close(handle);
+	
+	// Check data no corrupt
+	if (data_corrupt) {
+		FAIL_MSG("Data Corrupt in Device# = %d, DevType = %d", device, devtype);
+		return KAL_FALSE;
+	}
+	
+	// Check there is no assert
+	if (ut_assert_flag) {
+		ut_assert_flag = KAL_FALSE; // clear flag
+		FAIL_MSG("There is a assertion in exception. It's found at Test Case end");
+		return KAL_FALSE;
+	}
+	return KAL_TRUE;
+}
+
+/**************
+	Main-Case
+ **************/
+kal_bool DataPath_DirectlyPath(void *p_param, kal_char *p_ret_err_str, kal_uint32 *p_ret_err_str_sz)
+{
+	if (IS_SUB_CASE_FAIL(ConvTxPath))
+		return KAL_FALSE;
+	if (IS_SUB_CASE_FAIL(ConvRxPath))
+		return KAL_FALSE;
+	if (IS_SUB_CASE_FAIL(NewTxPath))
+		return KAL_FALSE;
+	if (IS_SUB_CASE_FAIL(NewTxLightPath))
+		return KAL_FALSE;
+	if (IS_SUB_CASE_FAIL(NewRxPath))
+		return KAL_FALSE;
+	if (IS_SUB_CASE_FAIL(BuffModTxPath))
+		return KAL_FALSE;
+	if (IS_SUB_CASE_FAIL(BuffModRxPath))
+		return KAL_FALSE;
+	
+	return KAL_TRUE;
+}
+
+kal_bool DataPath_LoopbackTest(void *p_param, kal_char *p_ret_err_str, kal_uint32 *p_ret_err_str_sz)
+{
+	if (IS_SUB_CASE_FAIL(NewTx_NewRx))
+		return KAL_FALSE;
+	if (IS_SUB_CASE_FAIL(NewTx_ConvRx))
+		return KAL_FALSE;
+	if (IS_SUB_CASE_FAIL(ConvTx_NewRx))
+		return KAL_FALSE;
+	if (IS_SUB_CASE_FAIL(ConvTx_ConvRx))
+		return KAL_FALSE;
+	if (IS_SUB_CASE_FAIL(BuffMod_ConvTx_ConvRx))
+		return KAL_FALSE;
+	
+	return KAL_TRUE;
+}
+
+/***********************************
+		UnitTest Begin End
+ ***********************************/
+kal_bool utTest_Initialize(void *p_param, kal_char *p_ret_err_str, kal_uint32 *p_ret_err_str_sz)
+{
+	kal_mem_set(Dev_Mgmt, 0, sizeof(UtInstance) * UART_DEV_CNT);
+	
+	return KAL_TRUE;
+}
+
+kal_bool utTest_End(void *p_param, kal_char *p_ret_err_str, kal_uint32 *p_ret_err_str_sz)
+{		
+	return KAL_TRUE;
+}
+
+/****************************************************************************
+                TTYUT Task Init Function
+ ***************************************************************************/
+
+#define UT_TEST(_func, param) { #_func, _func, param }
+ST_TCASE_T st_tcase_g[] = {
+	UT_TEST(utTest_Initialize, NULL),
+	
+	// Don't take out "FuncVeri_Common" case, DclSerialPort_Initialize will make test environment clear.
+	UT_TEST(FuncVeri_Common, NULL), 
+	
+	UT_TEST(FuncVeri_DrvRegDeRegCb, NULL),
+	UT_TEST(FuncVeri_DrvAtDetach, NULL),
+	UT_TEST(FuncVeri_UpInitDeinit, NULL),
+	UT_TEST(FuncVeri_UpRegCb, NULL),
+	UT_TEST(FuncVeri_ChangeOwner, NULL),
+	UT_TEST(FuncVeri_Misc, NULL),
+	
+	UT_TEST(DataPath_DirectlyPath, NULL),
+	UT_TEST(DataPath_LoopbackTest, NULL),
+	/// TODO: DataPath for ChangeOwner
+	
+	UT_TEST(utTest_End, NULL)
+};
+kal_uint32 st_tcase_count_g = sizeof(st_tcase_g) / sizeof(ST_TCASE_T);
+
+kal_bool tty_ut_st_create (void)
+{
+    return st_reg_test(ST_MOD_NAME,  /* p_mod_name */
+                     &st_tcase_g, /* p_tcase */
+                     st_tcase_count_g /* tcase_num */
+           );
+}
+
diff --git a/mcu/driver/tty/src/tty_ut.c b/mcu/driver/tty/src/tty_ut.c
new file mode 100644
index 0000000..a3f16ee
--- /dev/null
+++ b/mcu/driver/tty/src/tty_ut.c
@@ -0,0 +1,1779 @@
+/*****************************************************************************
+*  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:
+ * ---------
+ *   tty_ut.c
+ *
+ * Project:
+ * --------
+ *   MOLY
+ *
+ * Description:
+ * ------------
+ *   TTY Core unit test file - it needs Host Test Program to run test.
+ *
+ * Author:
+ * -------
+ * -------
+ *
+ * ==========================================================================
+ * $Log$
+ *
+ * 09 23 2019 bo-kai.huang
+ * [MOLY00357061] 97 Code Merge
+ * [TerTer]
+ *
+ * 10 21 2015 mt.tsai
+ * [MOLY00146136] Fix TTY Core ut program for SMP and set gpd's next to NULL
+ * give a UT Task instance on each port to prevent race condition & Set gpd's next as NULL
+ *
+ * 03 11 2015 i-wei.tsai
+ * [MOLY00097392] [UMOLY] [TTY] Timer tick macro modification
+ * 	.
+ *
+ * 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
+ *
+ * 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
+ *
+ * 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 <stdlib.h>
+#include <math.h>
+#include "kal_debug.h"
+//#include "kal_release.h"
+#include "syscomp_config.h"
+#include "kal_debug.h"
+#include "dcl.h"
+#include "qmu_bm.h"
+#include "qmu_bm_util.h"
+
+#include "devdrv_ls.h"
+#include "drv_msgid.h"
+#include "md_drv_sap.h"
+#include "kal_public_defs.h"
+#include "kal_public_api.h"
+
+/*for dhl trace*/
+#include "dhl_trace.h"
+
+#define TTY_UT_MISC_TEST  (0)    /* Set 1 to enable owner test and init/deinit test*/
+
+#define USB_TEST
+//#undef USB_TEST
+
+#if defined USB_TEST    /* USB COM */
+#define TTY_UT_COM_NUM  3
+#define TTY_UT_COM1     uart_port_usb3
+#define TTY_UT_COM2     uart_port_usb4     
+#define TTY_UT_COM3     uart_port_usb5    
+
+#else   /* UART COM */
+#define TTY_UT_COM_NUM  1
+#define TTY_UT_COM1     uart_port2
+#define TTY_UT_COM2     uart_port2
+#define TTY_UT_COM3     uart_port2
+#endif
+
+#if (TTY_UT_COM_NUM > 3)
+#error "COM number more than three does not support."
+#endif
+
+#define TTY_UT_TASK_1_PRIORITY 1
+#define TTY_UT_TASK_2_PRIORITY 2
+#define TTY_UT_TASK_3_PRIORITY 3
+
+#define IO_REQUEST_PUSH(_ori, _new) \
+{ \
+    tty_io_request_t *tmp_ior = _ori; \
+    while (tmp_ior->next_request != NULL) { \
+        tmp_ior = tmp_ior->next_request; \
+    } \
+    tmp_ior->next_request = _new; \
+}
+
+#define BUSY_WAIT(_loopCnt) do{unsigned int i,j;for(i=0;i<_loopCnt;i++){j=i;j++;}}while(0)
+
+typedef enum _tty_ut_mode {
+    TTY_UT_CONV_TX_ONLY = 0,
+    TTY_UT_NEW_TX_ONLY,
+    TTY_UT_CONV_RX_ONLY,
+    TTY_UT_NEW_RX_ONLY,
+    TTY_UT_CONV_TX_CONV_RX,
+    TTY_UT_CONV_TX_NEW_RX,
+    TTY_UT_NEW_TX_CONV_RX,
+    TTY_UT_NEW_TX_NEW_RX,
+    TTY_UT_NEW_INIT_CONV_TX_CONV_RX,
+    TTY_UT_BYPASS,                                          //This is used to disable test procedure
+} tty_ut_mode_e;
+
+static tty_ut_mode_e tty_ut_mode_1 = TTY_UT_NEW_TX_NEW_RX; //TTY_UT_NEW_TX_NEW_RX;
+static tty_ut_mode_e tty_ut_mode_2 = /*TTY_UT_NEW_TX_NEW_RX;*/ TTY_UT_CONV_TX_CONV_RX;
+static tty_ut_mode_e tty_ut_mode_3 = TTY_UT_NEW_TX_CONV_RX;
+
+// for conventional path
+#define TTY_UT_NEW_BUF_SIZE     QBM_TTY_XXX_DATA_LEN
+#define TTY_UT_CONV_BUF_SIZE    QBM_TTY_XXX_DATA_LEN*2
+
+#define TTY_UT_LB_CON_TX_TX_BUF_SIZE    QBM_TTY_XXX_DATA_LEN*10
+
+#define TTY_UT_CHUNK_SIZE_DEFAULT (QBM_TTY_XXX_DATA_LEN)
+
+typedef struct _ttyut_instance_t {
+    DCL_HANDLE              handle;
+    DCL_UINT32              owner;
+    tty_io_request_t        *ttyut_rx_ior;
+    kal_mutexid             ttyut_mutex;
+
+    kal_uint8 ttyut_rx_buf[TTY_UT_CONV_BUF_SIZE];
+    kal_uint8 ttyut_tx_buf[TTY_UT_CONV_BUF_SIZE];
+    kal_uint32 ttyut_tx_offset;
+    kal_uint32 ttyut_tx_len;
+
+    kal_uint8 conv_tx_rx_buf[TTY_UT_LB_CON_TX_TX_BUF_SIZE];
+    kal_uint32 conv_tx_rx_rd_idx;
+    kal_uint32 conv_tx_rx_wt_idx;
+    kal_uint32 conv_tx_rx_wrap;
+} ttyut_instance_t;
+static ttyut_instance_t ttyut_inst_g[uart_max_port];
+
+#if defined(__MTK_TARGET__)
+extern void dbg_print(char *fmt,...);
+#define ttyut_print dbg_print
+#else
+#define ttyut_print(...) dhl_print(TRACE_INFO, DHL_USER_FLAG_NONE, MOD_TTY, ##__VA_ARGS__)
+#endif
+
+#define DCL_UART_MAGIC_NUM 0x40000000
+#define DCL_UART_GET_DEV(handle_) ((DCL_DEV)((handle_) & (~DCL_UART_MAGIC_NUM)))
+
+// ==========================================================
+// Private Function
+// ==========================================================
+static kal_bool ttyut_create_instance(DCL_HANDLE handle, DCL_UINT32 owner)
+{
+    char mutex_name_str[64];
+    DCL_DEV uart_port = DCL_UART_GET_DEV(handle);
+
+    if (ttyut_inst_g[uart_port].handle == (DCL_HANDLE) 0x0) {
+
+        sprintf(mutex_name_str, "TTY_UT_%d", (int)handle);
+        ttyut_inst_g[uart_port].handle = handle;
+        ttyut_inst_g[uart_port].owner = owner;
+        ttyut_inst_g[uart_port].ttyut_rx_ior = NULL;
+        ttyut_inst_g[uart_port].ttyut_mutex = kal_create_mutex(mutex_name_str);
+        
+        return KAL_TRUE;
+    }
+
+    // Can't create TTY_UT instance, ASSERT.
+    ASSERT(0);
+    return KAL_FALSE;
+}
+
+static ttyut_instance_t* ttyut_get_instance(DCL_HANDLE handle)
+{
+    DCL_DEV uart_port = DCL_UART_GET_DEV(handle);
+
+    if (ttyut_inst_g[uart_port].handle == handle) {
+        return &ttyut_inst_g[uart_port];
+    }
+
+    return NULL;
+}
+
+
+// ==========================================================
+// Private Function
+// ==========================================================
+DCL_STATUS _ttyut_rx_cb(DCL_HANDLE handle, module_type source_id, tty_io_request_t *rx_ior)
+{
+    ttyut_instance_t *ttyut_inst_p;
+
+    ttyut_inst_p = ttyut_get_instance(handle);
+
+    kal_take_mutex(ttyut_inst_p->ttyut_mutex);
+    if (ttyut_inst_p->ttyut_rx_ior) {
+        IO_REQUEST_PUSH(ttyut_inst_p->ttyut_rx_ior, rx_ior);
+    } else {
+        ttyut_inst_p->ttyut_rx_ior = rx_ior;
+    }
+    kal_give_mutex(ttyut_inst_p->ttyut_mutex);
+
+    ttyut_print("=========>_ttyut_rx_cb\r\n");
+    return STATUS_OK;
+}
+
+DCL_STATUS _ttyut_tx_done_cb(DCL_HANDLE handle, module_type source_id, tty_io_request_t *tx_ior)
+{
+    if (tx_ior) {
+        /* free all GPDs of all IOR */
+        do {
+            qbmt_dest_q(tx_ior->first_gpd, tx_ior->last_gpd);
+        } while ((tx_ior = tx_ior->next_request) != NULL);
+    } else {
+        ttyut_print("[TTY UT] [ERROR] =========>_ttyut_tx_done_cb : tx_ior is NULL!!!!!\r\n");
+    }
+
+    ttyut_print("=========>_ttyut_tx_done_cb\r\n");
+    return STATUS_OK;
+}
+
+DCL_STATUS _ttyut_drv_state_cb(DCL_HANDLE handle, tty_drv_state_e state)
+{
+    ttyut_print("=========>_ttyut_drv_state_cb: state - %s\r\n", (state==DRV_ST_ATTACHED)?"attached":"detached");
+    return STATUS_OK;
+}
+
+DCL_STATUS _ttyut_hdr_main(DCL_DEV dev, DCL_CTRL_CMD cmd, DCL_CTRL_DATA_T *data)
+{
+    return STATUS_OK;
+}
+
+kal_bool _ttyut_upmod_init_deinit_test(kal_uint8 uart_port)
+{
+    #define TEST_ROUND  100
+    #define UART_INVALID_PORT 0xFFFF
+    DCL_STATUS status;
+    DCL_HANDLE handle;
+    int idx;
+    UART_CTRL_OPEN_T ur_ctrl_open;
+    UART_CTRL_CLOSE_T ur_ctrl_close;
+    Seriport_HANDLER_T tty_ut_uart_handler = {DCL_UART_USB_TYPE, _ttyut_hdr_main};
+
+    /*Test 1*/
+    /* Init non-existed port -> should init failed */
+    /* test invalid port 0xFFFF*/
+    handle = DclSerialPort_Open(UART_INVALID_PORT, 0);
+    if(handle != STATUS_INVALID_DEVICE)
+    {
+        ttyut_print("[ERROR][TTY UT] DCL upper module open non-existed port successfully");
+        return KAL_FALSE;
+    }
+    /* test non-exist port by invalid handle with NEW API*/
+    handle = 0xFFFF;
+    status = DclSerialPort_UpModuleInit(handle, MOD_TTY_UT, TTY_FLAG_NEW_TX | TTY_FLAG_NEW_RX);
+    if (status == STATUS_OK) {
+        ttyut_print("[ERROR][TTY UT] DCL upper module init non-existed port with NEW API successfully");
+        return KAL_FALSE;
+    }
+    /* test non-exist port by invalid handle with Conventional API*/
+    handle = 0xFFFF;
+    status = DclSerialPort_Control(handle, SIO_CMD_OPEN, (DCL_CTRL_DATA_T*) &ur_ctrl_open);
+    if (status == STATUS_OK) {
+        ttyut_print("[ERROR][TTY UT] DCL upper module init non-existed port with Conv API successfully");
+        return KAL_FALSE;
+    }
+
+    /*Test 2 : Driver reg/de-reg API test*/
+    /* First register callback -> should not return failed */
+    handle = DclSerialPort_Open(uart_max_port, 0);
+    for (idx = 0; idx < TEST_ROUND; idx ++)
+    {
+        status = DclSerialPort_DrvRegisterCb(handle, &tty_ut_uart_handler);
+        if (status != STATUS_OK) {
+            ttyut_print("[ERROR][TTY UT] Driver first register callback function failed");
+            return KAL_FALSE;
+        }
+        /* Duplicated register -> should return failed */
+        status = DclSerialPort_DrvRegisterCb(handle, &tty_ut_uart_handler);
+        if (status == STATUS_OK) {
+            ttyut_print("[ERROR][TTY UT] Driver first register callback function twice successfully");
+            return KAL_FALSE;
+        }
+        /* First De-register callback -> should not return failed */
+        status = DclSerialPort_DrvDeRegisterCb(handle);
+        if (status != STATUS_OK) {
+            ttyut_print("[ERROR][TTY UT] Driver first De-register callback function failed");
+            return KAL_FALSE;
+        }
+        /* Duplicated register -> should return failed */
+        status = DclSerialPort_DrvDeRegisterCb(handle);
+        if (status == STATUS_OK) {
+            ttyut_print("[ERROR][TTY UT] Driver De-register callback function twice successfully");
+            return KAL_FALSE;
+        }
+    }
+
+    /*Test 3 : open non-registered port with NEW API*/
+    /* Init non-register port -> should not return failed */
+    handle = DclSerialPort_Open(uart_max_port, 0);
+    for (idx = 0; idx < TEST_ROUND; idx ++)
+    {
+        status = DclSerialPort_UpModuleInit(handle, MOD_TTY_UT, TTY_FLAG_NEW_TX | TTY_FLAG_NEW_RX);
+        if (status != STATUS_OK) {
+            ttyut_print("[ERROR][TTY UT] DCL upper module first init non-registered port failed");
+            return KAL_FALSE;
+        }
+        /* Duplicated init -> should init failed */
+        status = DclSerialPort_UpModuleInit(handle, MOD_TTY_UT, TTY_FLAG_NEW_TX | TTY_FLAG_NEW_RX);
+        if (status == STATUS_OK) {
+            ttyut_print("[ERROR][TTY UT] DCL upper module init twice (non-registered port)successfully!!");
+            return KAL_FALSE;
+        }
+        /* First deinit -> should deinit successfully */
+        status = DclSerialPort_UpModuleDeinit(handle);
+        if (status != STATUS_OK) {
+            ttyut_print("[ERROR][TTY UT] DCL upper module first deinit non-registered port failed");
+            return KAL_FALSE;
+        }
+        /* Duplicated deinit -> should deinit failed */
+        status = DclSerialPort_UpModuleDeinit(handle);
+        if (status == STATUS_OK) {
+            ttyut_print("[ERROR][TTY UT] DCL upper module deinit twice (non-registered port)successfully!!");
+            return KAL_FALSE;
+        }
+    }
+
+    /*Test 4 : open non-registered port with Conv API*/
+    /* Init non-register port -> should not return failed */
+    handle = DclSerialPort_Open(uart_max_port, 0);
+    ur_ctrl_open.u4OwenrId = MOD_TTY_UT;
+    ur_ctrl_close.u4OwenrId = MOD_TTY_UT;
+    for (idx = 0; idx < TEST_ROUND; idx ++)
+    {
+        status = DclSerialPort_Control(handle, SIO_CMD_OPEN, (DCL_CTRL_DATA_T*) &ur_ctrl_open);
+        if (status != STATUS_OK) {
+            ttyut_print("[ERROR][TTY UT] DCL upper module first init non-registered port failed");
+            return KAL_FALSE;
+        }
+        /* Duplicated init -> should init failed */
+        status = DclSerialPort_Control(handle, SIO_CMD_OPEN, (DCL_CTRL_DATA_T*) &ur_ctrl_open);
+        if (status == STATUS_OK) {
+            ttyut_print("[ERROR][TTY UT] DCL upper module init twice (non-registered port)successfully!!");
+            return KAL_FALSE;
+        }
+        /* First deinit -> should deinit successfully */
+        status = DclSerialPort_Control(handle, SIO_CMD_CLOSE, (DCL_CTRL_DATA_T*) &ur_ctrl_close);
+        if (status != STATUS_OK) {
+            ttyut_print("[ERROR][TTY UT] DCL upper module first deinit non-registered port failed");
+            return KAL_FALSE;
+        }
+        /* Duplicated deinit -> should deinit failed */
+        status = DclSerialPort_Control(handle, SIO_CMD_CLOSE, (DCL_CTRL_DATA_T*) &ur_ctrl_close);
+        if (status == STATUS_OK) {
+            ttyut_print("[ERROR][TTY UT] DCL upper module deinit twice (non-registered port)successfully!!");
+            return KAL_FALSE;
+        }
+    }
+
+    /*Test 5 : open registered port test*/
+    handle = DclSerialPort_Open(uart_port, 0);
+    for (idx = 0; idx < TEST_ROUND; idx ++)
+    {
+        /* First init -> should init successfully */
+        status = DclSerialPort_UpModuleInit(handle, MOD_TTY_UT, TTY_FLAG_NEW_TX | TTY_FLAG_NEW_RX);
+        if (status != STATUS_OK) {
+            ttyut_print("[ERROR][TTY UT] DCL upper module init failed");
+            return KAL_FALSE;
+        }
+        DclSerialPort_UpModuleRegisterCb(handle, _ttyut_rx_cb, NULL, _ttyut_drv_state_cb);
+
+        /* Duplicated init -> should init failed */
+        status = DclSerialPort_UpModuleInit(handle, MOD_TTY_UT, TTY_FLAG_NEW_TX | TTY_FLAG_NEW_RX);
+        if (status == STATUS_OK) {
+            ttyut_print("[ERROR][TTY UT] DCL upper module init twice successfully!!");
+            return KAL_FALSE;
+        }
+
+        /* First deinit -> should deinit successfully */
+        status = DclSerialPort_UpModuleDeinit(handle);
+        if (status != STATUS_OK) {
+            ttyut_print("[ERROR][TTY UT] DCL upper module init failed");
+            return KAL_FALSE;
+        }
+
+        /* Duplicated deinit -> should deinit failed */
+        status = DclSerialPort_UpModuleDeinit(handle);
+        if (status == STATUS_OK) {
+            ttyut_print("[ERROR][TTY UT] DCL upper module init failed");
+            return KAL_FALSE;
+        }
+    }
+
+    return KAL_TRUE;
+}
+
+kal_bool _ttyut_upmod_change_owner_test()
+{
+    DCL_STATUS status;
+    DCL_HANDLE handle;  
+    UART_CTRL_OPEN_T ur_ctrl_open;
+    UART_CTRL_CLOSE_T ur_ctrl_close;
+    UART_CTRL_OWNER_T ur_ctrl_owner;
+    UART_CTRL_GET_DRV_STATE_T getDrvState;
+    UART_CTRL_GET_CHUNK_SIZE_T getChunkSize;
+    
+    handle = DclSerialPort_Open(TTY_UT_COM1, 0);
+
+    kal_sleep_task(KAL_TICKS_3_SEC);
+
+
+    /* Conventional owner change to conventional owner */
+    {
+        UART_CTRL_PUT_BYTES_T ur_ctrl_putbytes;
+        char *test_string1 = "[Change owner test] Conventional Owner A change to ";
+        char *test_string2 = "Conventional owner B\r\n";
+        
+        ur_ctrl_open.u4OwenrId = MOD_TTY_UT;
+        DclSerialPort_Control(handle, SIO_CMD_OPEN, (DCL_CTRL_DATA_T*) &ur_ctrl_open);
+
+        /* Send string */
+        ur_ctrl_putbytes.u4OwenrId = MOD_TTY_UT;
+        ur_ctrl_putbytes.puBuffaddr = (DCL_UINT8*)test_string1;
+        ur_ctrl_putbytes.u2Length = strlen(test_string1);
+        DclSerialPort_Control(handle, SIO_CMD_PUT_BYTES, (DCL_CTRL_DATA_T*) &ur_ctrl_putbytes);
+        kal_sleep_task(KAL_TICKS_10_MSEC/10);
+
+        /* Change owner to MOD_TTY_UT99 */
+        ur_ctrl_owner.u4OwenrId = MOD_TTY_UT99;
+        DclSerialPort_Control(handle, SIO_CMD_SET_OWNER, (DCL_CTRL_DATA_T*) &ur_ctrl_owner);
+
+        kal_set_active_module_id(MOD_TTY_UT99);
+        
+        /* Send string */
+        ur_ctrl_putbytes.u4OwenrId = MOD_TTY_UT99;
+        ur_ctrl_putbytes.puBuffaddr = (DCL_UINT8*)test_string2;
+        ur_ctrl_putbytes.u2Length = strlen(test_string2);
+        DclSerialPort_Control(handle, SIO_CMD_PUT_BYTES, (DCL_CTRL_DATA_T*) &ur_ctrl_putbytes);
+        kal_sleep_task(KAL_TICKS_10_MSEC/10);
+
+        /* Close com port */
+        ur_ctrl_close.u4OwenrId = MOD_TTY_UT99;
+        DclSerialPort_Control(handle, SIO_CMD_CLOSE, (DCL_CTRL_DATA_T*) &ur_ctrl_close);
+
+        kal_set_active_module_id(MOD_TTY_UT);
+    }
+
+    BUSY_WAIT(1000);
+    
+    /* Conventional owner change to new owner */
+    {
+        UART_CTRL_PUT_BYTES_T ur_ctrl_putbytes;
+        char *test_string1 = "[Change owner test] Conventional Owner A change to ";
+        char *test_string2 = "New owner B\r\n";
+        void *tx_gpd;
+        tty_io_request_t *tx_ior;
+        unsigned char *tx_buf_ptr;
+
+        ur_ctrl_open.u4OwenrId = MOD_TTY_UT;
+        DclSerialPort_Control(handle, SIO_CMD_OPEN, (DCL_CTRL_DATA_T*) &ur_ctrl_open);
+
+        /* Send string */
+        ur_ctrl_putbytes.u4OwenrId = MOD_TTY_UT;
+        ur_ctrl_putbytes.puBuffaddr = (DCL_UINT8*)test_string1;
+        ur_ctrl_putbytes.u2Length = strlen(test_string1);
+        DclSerialPort_Control(handle, SIO_CMD_PUT_BYTES, (DCL_CTRL_DATA_T*) &ur_ctrl_putbytes);
+        kal_sleep_task(KAL_TICKS_10_MSEC/10);
+
+        /* Change owner to MOD_TTY_UT99 */
+        ur_ctrl_owner.u4OwenrId = MOD_TTY_UT99;
+        DclSerialPort_Control(handle, SIO_CMD_SET_OWNER, (DCL_CTRL_DATA_T*) &ur_ctrl_owner);
+        kal_set_active_module_id(MOD_TTY_UT99);
+        DclSerialPort_UpModuleReinit(handle, MOD_TTY_UT99, TTY_FLAG_NEW_TX | TTY_FLAG_NEW_RX);
+        DclSerialPort_UpModuleRegisterCb(handle, _ttyut_rx_cb, NULL, _ttyut_drv_state_cb);
+
+        // Wait for device ready
+        getDrvState.u4OwnerId = MOD_TTY_UT;
+        do {
+            kal_sleep_task(KAL_TICKS_100_MSEC);
+            status = DclSerialPort_Control(handle, TTY_CMD_GET_DRV_STATE, (DCL_CTRL_DATA_T*) &getDrvState);
+        } while (getDrvState.drv_state != DRV_ST_ATTACHED);
+
+        // Get chunk size
+        do {
+            kal_sleep_task(KAL_TICKS_100_MSEC);
+            status = DclSerialPort_Control(handle, TTY_CMD_GET_CHUNK_SIZE, (DCL_CTRL_DATA_T*) &getChunkSize);
+        } while (status != STATUS_OK);
+
+        /* Send string */
+        tx_gpd = QBM_ALLOC_ONE(QBM_TYPE_TTY_TYPE1);
+        if (tx_gpd) {
+            tx_ior = (tty_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;
+            
+            tx_buf_ptr = QBM_DES_GET_DATAPTR(tx_gpd);
+            kal_mem_cpy((void*)tx_buf_ptr, test_string2, strlen(test_string2));
+            QBM_DES_SET_DATALEN(tx_gpd, strlen(test_string2)); // Set data length
+
+            QBM_DES_SET_HWO(tx_gpd);
+            qbm_cal_set_checksum(tx_gpd);
+            //QBM_CACHE_FLUSH(tx_gpd, sizeof(qbm_gpd));
+
+            DclSerialPort_UpModuleTransmit(handle, tx_ior);
+        } else {
+            ttyut_print("[ERROR] [TTY UT] GPD allocate failed in QBM_TYPE_TTY_TYPE1 type\r\n");
+            return KAL_FALSE;
+        }
+        kal_sleep_task(KAL_TICKS_10_MSEC/10);
+
+        /* Close com port */
+        DclSerialPort_UpModuleDeinit(handle);
+
+        kal_set_active_module_id(MOD_TTY_UT);
+    }
+
+    BUSY_WAIT(1000);
+
+    /* New owner change to new owner */
+    {
+        char *test_string1 = "[Change owner test] New Owner A change to ";
+        char *test_string2 = "New owner B\r\n";
+        void *tx_gpd;
+        tty_io_request_t *tx_ior;
+        unsigned char *tx_buf_ptr;      
+        UART_CTRL_CLR_BUFFER_T ur_ctrl_clr_buf;
+
+        /* Bind COM port - initialization */
+        status = DclSerialPort_UpModuleInit(handle, MOD_TTY_UT, TTY_FLAG_NEW_TX | TTY_FLAG_NEW_RX);
+        if (status != STATUS_OK) {
+            ttyut_print("[TTY UT] DCL upper module init failed");
+            return KAL_FALSE;
+        } else {
+            DclSerialPort_UpModuleRegisterCb(handle, _ttyut_rx_cb, NULL, _ttyut_drv_state_cb);
+            // Wait for device ready
+            getDrvState.u4OwnerId = MOD_TTY_UT;
+            do {
+                kal_sleep_task(KAL_TICKS_100_MSEC);
+                status = DclSerialPort_Control(handle, TTY_CMD_GET_DRV_STATE, (DCL_CTRL_DATA_T*) &getDrvState);
+            } while (getDrvState.drv_state != DRV_ST_ATTACHED);
+
+            // Get chunk size
+            do {
+                kal_sleep_task(KAL_TICKS_100_MSEC);
+                status = DclSerialPort_Control(handle, TTY_CMD_GET_CHUNK_SIZE, (DCL_CTRL_DATA_T*) &getChunkSize);
+            } while (status != STATUS_OK);  
+        }
+        
+        /* Send string */
+        tx_gpd = QBM_ALLOC_ONE(QBM_TYPE_TTY_TYPE1);
+        if (tx_gpd) {
+            tx_ior = (tty_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;
+            
+            tx_buf_ptr = QBM_DES_GET_DATAPTR(tx_gpd);
+            kal_mem_cpy((void*)tx_buf_ptr, test_string1, strlen(test_string1));
+            QBM_DES_SET_DATALEN(tx_gpd, strlen(test_string1)); // Set data length
+
+            QBM_DES_SET_HWO(tx_gpd);
+            qbm_cal_set_checksum(tx_gpd);
+            QBM_CACHE_FLUSH(tx_gpd, sizeof(qbm_gpd));
+
+            DclSerialPort_UpModuleTransmit(handle, tx_ior);
+        } else {
+            ttyut_print("[ERROR] [TTY UT] GPD allocate failed in QBM_TYPE_TTY_TYPE1 type\r\n");
+            return KAL_FALSE;
+        }
+        kal_sleep_task(KAL_TICKS_10_MSEC/10);
+
+        /* Send Clear Tx/Rx buffer commands */
+        ur_ctrl_clr_buf.u4OwenrId = MOD_TTY_UT; 
+        DclSerialPort_Control(handle, SIO_CMD_CLR_TX_BUF, (DCL_CTRL_DATA_T*) &ur_ctrl_clr_buf);
+        DclSerialPort_Control(handle, SIO_CMD_CLR_RX_BUF, (DCL_CTRL_DATA_T*) &ur_ctrl_clr_buf);
+
+        /* Change owner to MOD_TTY_UT99 */
+        ur_ctrl_owner.u4OwenrId = MOD_TTY_UT99;
+        DclSerialPort_Control(handle, SIO_CMD_SET_OWNER, (DCL_CTRL_DATA_T*) &ur_ctrl_owner);
+        kal_set_active_module_id(MOD_TTY_UT99);
+        DclSerialPort_UpModuleReinit(handle, MOD_TTY_UT99, TTY_FLAG_NEW_TX | TTY_FLAG_NEW_RX);
+        DclSerialPort_UpModuleRegisterCb(handle, _ttyut_rx_cb, NULL, _ttyut_drv_state_cb);
+
+        // Wait for device ready
+        getDrvState.u4OwnerId = MOD_TTY_UT;
+        do {
+            kal_sleep_task(KAL_TICKS_100_MSEC);
+            status = DclSerialPort_Control(handle, TTY_CMD_GET_DRV_STATE, (DCL_CTRL_DATA_T*) &getDrvState);
+        } while (getDrvState.drv_state != DRV_ST_ATTACHED);
+
+        // Get chunk size
+        do {
+            kal_sleep_task(KAL_TICKS_100_MSEC);
+            status = DclSerialPort_Control(handle, TTY_CMD_GET_CHUNK_SIZE, (DCL_CTRL_DATA_T*) &getChunkSize);
+        } while (status != STATUS_OK);
+
+        /* Send string */
+        tx_gpd = QBM_ALLOC_ONE(QBM_TYPE_TTY_TYPE1);
+        if (tx_gpd) {
+            tx_ior = (tty_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;
+            
+            tx_buf_ptr = QBM_DES_GET_DATAPTR(tx_gpd);
+            kal_mem_cpy((void*)tx_buf_ptr, test_string2, strlen(test_string2));
+            QBM_DES_SET_DATALEN(tx_gpd, strlen(test_string2)); // Set data length
+
+            QBM_DES_SET_HWO(tx_gpd);
+            qbm_cal_set_checksum(tx_gpd);
+            //QBM_CACHE_FLUSH(tx_gpd, sizeof(qbm_gpd));
+
+            DclSerialPort_UpModuleTransmit(handle, tx_ior);
+        } else {
+            ttyut_print("[ERROR] [TTY UT] GPD allocate failed in QBM_TYPE_TTY_TYPE1 type\r\n");
+            return KAL_FALSE;
+        }
+        kal_sleep_task(KAL_TICKS_10_MSEC/10);
+
+        /* Close com port */
+        DclSerialPort_UpModuleDeinit(handle);
+
+        kal_set_active_module_id(MOD_TTY_UT);
+    }
+
+    BUSY_WAIT(1000);
+
+    /* New owner change to conventional owner */
+    {
+        UART_CTRL_PUT_BYTES_T ur_ctrl_putbytes;
+        char *test_string1 = "[Change owner test] New Owner A change to ";
+        char *test_string2 = "Conventional owner B\r\nPASS\r\n";
+        void *tx_gpd;
+        tty_io_request_t *tx_ior;
+        unsigned char *tx_buf_ptr;
+        UART_CTRL_CLR_BUFFER_T ur_ctrl_clr_buf;
+            
+        /* Bind COM port - initialization */
+        status = DclSerialPort_UpModuleInit(handle, MOD_TTY_UT, TTY_FLAG_NEW_TX | TTY_FLAG_NEW_RX);
+        if (status != STATUS_OK) {
+            ttyut_print("[TTY UT] DCL upper module init failed");
+            return KAL_FALSE;
+        } else {
+            DclSerialPort_UpModuleRegisterCb(handle, _ttyut_rx_cb, NULL, _ttyut_drv_state_cb);
+
+            // Wait for device ready
+            getDrvState.u4OwnerId = MOD_TTY_UT;
+
+            do {
+                kal_sleep_task(KAL_TICKS_100_MSEC);
+                status = DclSerialPort_Control(handle, TTY_CMD_GET_DRV_STATE, (DCL_CTRL_DATA_T*) &getDrvState);
+            } while (getDrvState.drv_state != DRV_ST_ATTACHED);
+
+            // Get chunk size
+            do {
+                kal_sleep_task(KAL_TICKS_100_MSEC);
+                status = DclSerialPort_Control(handle, TTY_CMD_GET_CHUNK_SIZE, (DCL_CTRL_DATA_T*) &getChunkSize);
+            } while (status != STATUS_OK);
+        }
+        
+        /* Send string */
+        tx_gpd = QBM_ALLOC_ONE(QBM_TYPE_TTY_TYPE1);
+        if (tx_gpd) {
+            tx_ior = (tty_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;
+            
+            tx_buf_ptr = QBM_DES_GET_DATAPTR(tx_gpd);
+            kal_mem_cpy((void*)tx_buf_ptr, test_string1, strlen(test_string1));
+            QBM_DES_SET_DATALEN(tx_gpd, strlen(test_string1)); // Set data length
+
+            QBM_DES_SET_HWO(tx_gpd);
+            qbm_cal_set_checksum(tx_gpd);
+            //QBM_CACHE_FLUSH(tx_gpd, sizeof(qbm_gpd));
+
+            DclSerialPort_UpModuleTransmit(handle, tx_ior);
+        } else {
+            ttyut_print("[ERROR] [TTY UT] GPD allocate failed in QBM_TYPE_TTY_TYPE1 type\r\n");
+            return KAL_FALSE;
+        }
+        kal_sleep_task(KAL_TICKS_10_MSEC/10);
+
+        /* Send Clear Tx/Rx buffer commands */
+        ur_ctrl_clr_buf.u4OwenrId = MOD_TTY_UT;
+        DclSerialPort_Control(handle, SIO_CMD_CLR_TX_BUF, (DCL_CTRL_DATA_T*) &ur_ctrl_clr_buf);
+        DclSerialPort_Control(handle, SIO_CMD_CLR_RX_BUF, (DCL_CTRL_DATA_T*) &ur_ctrl_clr_buf);
+
+        /* Change owner to MOD_TTY_UT99 */
+        ur_ctrl_owner.u4OwenrId = MOD_TTY_UT99;
+        DclSerialPort_Control(handle, SIO_CMD_SET_OWNER, (DCL_CTRL_DATA_T*) &ur_ctrl_owner);
+
+        kal_set_active_module_id(MOD_TTY_UT99);
+
+        /* Send string */
+        ur_ctrl_putbytes.u4OwenrId = MOD_TTY_UT99;
+        ur_ctrl_putbytes.puBuffaddr = (DCL_UINT8*)test_string2;
+        ur_ctrl_putbytes.u2Length = strlen(test_string2);
+        DclSerialPort_Control(handle, SIO_CMD_PUT_BYTES, (DCL_CTRL_DATA_T*) &ur_ctrl_putbytes);
+        kal_sleep_task(KAL_TICKS_10_MSEC/10);
+
+        /* Close com port */
+        ur_ctrl_close.u4OwenrId = MOD_TTY_UT99;
+        DclSerialPort_Control(handle, SIO_CMD_CLOSE, (DCL_CTRL_DATA_T*) &ur_ctrl_close);
+
+        kal_set_active_module_id(MOD_TTY_UT);
+    }
+
+    BUSY_WAIT(1000);
+
+    return KAL_TRUE;
+}
+
+static kal_bool ttyut_test_preproc(tty_ut_mode_e test_mode, kal_uint8 uart_port)
+{
+    DCL_STATUS status;
+    DCL_HANDLE handle;
+    DCL_UINT32 owner = MOD_NIL;
+
+    handle = DclSerialPort_Open(uart_port, 0);
+
+    if (TTY_UT_COM1 == uart_port) {
+        owner = MOD_TTY_UT;
+    } else if (TTY_UT_COM2 == uart_port) {
+        owner = MOD_TTY_UT2;
+    } else if (TTY_UT_COM3 == uart_port) {
+        owner = MOD_TTY_UT3;
+    } else {
+        // Unsupported mode, ASSERT.
+        ASSERT(0);
+    }
+    ttyut_create_instance(handle, owner);
+
+    switch (test_mode)
+    {
+        case TTY_UT_BYPASS:
+            {
+                //Do nothing;
+                break;
+            }
+        case TTY_UT_CONV_TX_CONV_RX:
+        case TTY_UT_CONV_TX_ONLY:
+        case TTY_UT_CONV_RX_ONLY:
+            {
+                UART_CTRL_OPEN_T data;
+                data.u4OwenrId = owner;
+                DclSerialPort_Control(handle, SIO_CMD_OPEN, (DCL_CTRL_DATA_T*) &data);
+            }
+            break;
+
+        case TTY_UT_NEW_INIT_CONV_TX_CONV_RX:
+            {
+                status = DclSerialPort_UpModuleInit(handle, owner, 0);
+                if (status != STATUS_OK) {
+                    ttyut_print("[TTY UT] DCL upper module init failed");
+                }
+            }
+            break;
+        case TTY_UT_NEW_TX_NEW_RX:  
+        case TTY_UT_NEW_TX_ONLY:
+        case TTY_UT_NEW_RX_ONLY:
+            {
+                void *rx_gpd_first, *rx_gpd_last;
+                tty_io_request_t *rx_ior;
+                void *rx_gpd_tmp;
+                int i;
+                UART_CTRL_GET_DRV_STATE_T getDrvState;
+                UART_CTRL_GET_CHUNK_SIZE_T getChunkSize;
+                
+                /* Bind COM port - initialization */
+                status = DclSerialPort_UpModuleInit(handle, owner, TTY_FLAG_NEW_TX | TTY_FLAG_NEW_RX);
+                if (status != STATUS_OK) {
+                    ttyut_print("[TTY UT] DCL upper module init failed");
+                } else {
+                    DclSerialPort_UpModuleRegisterCb(handle, _ttyut_rx_cb, _ttyut_tx_done_cb, _ttyut_drv_state_cb);
+
+                    // Wait for device ready
+                    getDrvState.u4OwnerId = owner;
+                    do {
+                        kal_sleep_task(KAL_TICKS_100_MSEC);
+                        status = DclSerialPort_Control(handle, TTY_CMD_GET_DRV_STATE, (DCL_CTRL_DATA_T*) &getDrvState);
+                    } while ((getDrvState.drv_state != DRV_ST_ATTACHED) || (status != STATUS_OK));
+
+                    // Get chunk size
+                    do {
+                        kal_sleep_task(KAL_TICKS_100_MSEC);
+                        status = DclSerialPort_Control(handle, TTY_CMD_GET_CHUNK_SIZE, (DCL_CTRL_DATA_T*) &getChunkSize);
+                    } while (status != STATUS_OK);
+
+                    qbmt_alloc_q_no_tail(QBM_TYPE_TTY_TYPE1, 2, &rx_gpd_first, &rx_gpd_last);
+                    rx_gpd_tmp = rx_gpd_first;
+
+                    if (!rx_gpd_first || !rx_gpd_last) {
+                        ttyut_print("[TTY UT] DCL upper module init failed");
+                        return KAL_FALSE;
+                    }
+                                        
+                    // Set allow length
+                    for (i=0; i<2; i++) {
+                        if(getChunkSize.chunkSize == 1)  //Some HIF doesn't have chunksize restrictions(ex: uart)
+                        {
+                            QBM_DES_SET_ALLOW_LEN(rx_gpd_tmp, TTY_UT_CHUNK_SIZE_DEFAULT);
+                        }
+                        else
+                        {
+                            QBM_DES_SET_ALLOW_LEN(rx_gpd_tmp, (kal_uint16)getChunkSize.chunkSize);
+                        }
+                        qbm_cal_set_checksum((kal_uint8*)rx_gpd_tmp);
+                        QBM_CACHE_FLUSH(rx_gpd_tmp, sizeof(qbm_gpd));
+                        rx_gpd_tmp = QBM_DES_GET_NEXT(rx_gpd_tmp);
+                    }
+                    
+                    rx_ior = (tty_io_request_t*)QBM_DES_GET_SW_CTRL_FIELD(rx_gpd_first);
+                    rx_ior->next_request = NULL;
+                    rx_ior->first_gpd = rx_gpd_first;
+                    rx_ior->last_gpd = rx_gpd_last;
+                    
+                    DclSerialPort_UpModuleAssignRxIor(handle, rx_ior);
+                }
+            }
+            break;
+
+        case TTY_UT_CONV_TX_NEW_RX:
+            {
+                void *rx_gpd_first, *rx_gpd_last;
+                tty_io_request_t *rx_ior;
+                void *rx_gpd_tmp;
+                int i;
+                UART_CTRL_GET_DRV_STATE_T getDrvState;
+                UART_CTRL_GET_CHUNK_SIZE_T getChunkSize;
+                
+                /* Bind COM port - initialization */
+                status = DclSerialPort_UpModuleInit(handle, owner, TTY_FLAG_NEW_RX);
+                if (status != STATUS_OK) {
+                    ttyut_print("[TTY UT] DCL upper module init failed");
+                } else {
+                    DclSerialPort_UpModuleRegisterCb(handle, _ttyut_rx_cb, NULL, _ttyut_drv_state_cb);
+
+                    // Wait for device ready
+                    getDrvState.u4OwnerId = owner;
+                    do {
+                        kal_sleep_task(KAL_TICKS_100_MSEC);
+                        status = DclSerialPort_Control(handle, TTY_CMD_GET_DRV_STATE, (DCL_CTRL_DATA_T*) &getDrvState);
+                    } while ((getDrvState.drv_state != DRV_ST_ATTACHED) || (status != STATUS_OK));
+
+                    // Get chunk size
+                    do {
+                        kal_sleep_task(KAL_TICKS_100_MSEC);
+                        status = DclSerialPort_Control(handle, TTY_CMD_GET_CHUNK_SIZE, (DCL_CTRL_DATA_T*) &getChunkSize);
+                    } while (status != STATUS_OK);
+
+                    qbmt_alloc_q_no_tail(QBM_TYPE_TTY_TYPE1, 2, &rx_gpd_first, &rx_gpd_last);
+                    rx_gpd_tmp = rx_gpd_first;
+
+                    if (!rx_gpd_first || !rx_gpd_last) {
+                        ttyut_print("[TTY UT] DCL upper module init failed");
+                        return KAL_FALSE;
+                    }
+
+                    // Set allow length
+                    for (i=0; i<2; i++) {
+                        QBM_DES_SET_ALLOW_LEN(rx_gpd_tmp, (kal_uint16)getChunkSize.chunkSize);
+                        qbm_cal_set_checksum((kal_uint8*)rx_gpd_tmp);
+                        QBM_CACHE_FLUSH(rx_gpd_tmp, sizeof(qbm_gpd));
+                        rx_gpd_tmp = QBM_DES_GET_NEXT(rx_gpd_tmp);
+                    }
+
+                    rx_ior = (tty_io_request_t*)QBM_DES_GET_SW_CTRL_FIELD(rx_gpd_first);
+                    rx_ior->next_request = NULL;
+                    rx_ior->first_gpd = rx_gpd_first;
+                    rx_ior->last_gpd = rx_gpd_last;
+
+                    DclSerialPort_UpModuleAssignRxIor(handle, rx_ior);
+                }
+            }
+            break;
+
+        case TTY_UT_NEW_TX_CONV_RX:
+            {
+                UART_CTRL_GET_DRV_STATE_T getDrvState;
+
+                /* Bind COM port - initialization */
+                status = DclSerialPort_UpModuleInit(handle, owner, TTY_FLAG_NEW_TX);
+                if (status != STATUS_OK) {
+                    ttyut_print("[TTY UT] DCL upper module init failed");
+                } else {
+                    DclSerialPort_UpModuleRegisterCb(handle, NULL, NULL, _ttyut_drv_state_cb);
+
+                    // Wait for device ready
+                    getDrvState.u4OwnerId = owner;
+                    do {
+                        kal_sleep_task(KAL_TICKS_100_MSEC);
+                        status = DclSerialPort_Control(handle, TTY_CMD_GET_DRV_STATE, (DCL_CTRL_DATA_T*) &getDrvState);
+                    } while ((getDrvState.drv_state != DRV_ST_ATTACHED) || (status != STATUS_OK));
+                }
+            }
+            break;
+            
+        default:
+            break;
+    }
+
+    return KAL_TRUE;
+}
+
+static void _tty_ut_conv_tx_conv_rx_rd_handler(DCL_HANDLE handle)
+{
+    UART_CTRL_GET_BYTES_T ur_ctrl_getbytes;
+    UART_CTRL_PUT_BYTES_T ur_ctrl_putbytes;
+    ttyut_instance_t *ttyut_inst_p;
+
+    ttyut_inst_p = ttyut_get_instance(handle);
+    ur_ctrl_getbytes.u4OwenrId = ttyut_inst_p->owner;
+    ur_ctrl_getbytes.puBuffaddr = ttyut_inst_p->conv_tx_rx_buf + ttyut_inst_p->conv_tx_rx_rd_idx;
+    ur_ctrl_getbytes.u2Length = ttyut_inst_p->conv_tx_rx_wrap
+                                ? (ttyut_inst_p->conv_tx_rx_wt_idx - ttyut_inst_p->conv_tx_rx_rd_idx)
+                                : (TTY_UT_LB_CON_TX_TX_BUF_SIZE - ttyut_inst_p->conv_tx_rx_rd_idx);
+    if (ur_ctrl_getbytes.u2Length == 0) {
+        return;
+    }
+    
+    if (STATUS_OK == DclSerialPort_Control(handle, SIO_CMD_GET_BYTES, (DCL_CTRL_DATA_T*) &ur_ctrl_getbytes)
+        && ur_ctrl_getbytes.u2RetSize > 0)
+    {
+        ttyut_inst_p->conv_tx_rx_rd_idx += ur_ctrl_getbytes.u2RetSize;
+        
+        if (ttyut_inst_p->conv_tx_rx_rd_idx == TTY_UT_LB_CON_TX_TX_BUF_SIZE ) {
+            /* reach the end of buffer, wrap to head */
+            ASSERT(ttyut_inst_p->conv_tx_rx_wrap == 0);
+            ttyut_inst_p->conv_tx_rx_rd_idx = 0;
+            ttyut_inst_p->conv_tx_rx_wrap = 1;
+        }
+
+        ur_ctrl_putbytes.u4OwenrId = ttyut_inst_p->owner;
+        ur_ctrl_putbytes.puBuffaddr = ttyut_inst_p->conv_tx_rx_buf + ttyut_inst_p->conv_tx_rx_wt_idx;
+        ur_ctrl_putbytes.u2Length = ttyut_inst_p->conv_tx_rx_wrap
+                                    ? (TTY_UT_LB_CON_TX_TX_BUF_SIZE - ttyut_inst_p->conv_tx_rx_wt_idx)
+                                    : (ttyut_inst_p->conv_tx_rx_rd_idx - ttyut_inst_p->conv_tx_rx_wt_idx);
+        ASSERT(ur_ctrl_putbytes.u2Length > 0);
+    
+        if (STATUS_OK == DclSerialPort_Control(handle, SIO_CMD_PUT_BYTES, (DCL_CTRL_DATA_T*) &ur_ctrl_putbytes)
+            && ur_ctrl_putbytes.u2RetSize > 0)
+        {
+            ttyut_inst_p->conv_tx_rx_wt_idx += ur_ctrl_putbytes.u2RetSize;
+            
+            if (ttyut_inst_p->conv_tx_rx_wt_idx == TTY_UT_LB_CON_TX_TX_BUF_SIZE ) {
+                /* reach the end of buffer, de-wrap to head */
+                ASSERT(ttyut_inst_p->conv_tx_rx_wrap == 1);
+                ttyut_inst_p->conv_tx_rx_wt_idx = 0;
+                ttyut_inst_p->conv_tx_rx_wrap = 0;
+
+                if (ttyut_inst_p->conv_tx_rx_rd_idx > 0) {
+                    ur_ctrl_putbytes.u4OwenrId = ttyut_inst_p->owner;
+                    ur_ctrl_putbytes.puBuffaddr = ttyut_inst_p->conv_tx_rx_buf;
+                    ur_ctrl_putbytes.u2Length = ttyut_inst_p->conv_tx_rx_rd_idx - ttyut_inst_p->conv_tx_rx_wt_idx;
+                    if (STATUS_OK == DclSerialPort_Control(handle, SIO_CMD_PUT_BYTES, (DCL_CTRL_DATA_T*) &ur_ctrl_putbytes)
+                        && ur_ctrl_putbytes.u2RetSize > 0)
+                    {
+                        ttyut_inst_p->conv_tx_rx_wt_idx += ur_ctrl_putbytes.u2RetSize;
+                    }
+                }
+            }
+        }
+    }
+}
+
+static void _ttyut_process_ilm(DCL_HANDLE handle, ilm_struct *ilm_ptr, tty_ut_mode_e test_mode)
+{
+    ttyut_instance_t *ttyut_inst_p;
+
+    ASSERT(ilm_ptr != NULL);
+
+    ttyut_inst_p = ttyut_get_instance(handle);
+
+    if (ilm_ptr != NULL)
+    {
+        switch (ilm_ptr->msg_id)
+        {
+            case MSG_ID_UART_READY_TO_WRITE_IND:
+                {
+                    UART_CTRL_PUT_BYTES_T ur_ctrl_putbytes;
+                    
+                    if (test_mode == TTY_UT_CONV_TX_CONV_RX || test_mode == TTY_UT_NEW_INIT_CONV_TX_CONV_RX)
+                    {
+                        ur_ctrl_putbytes.u4OwenrId = ttyut_inst_p->owner;
+                        ur_ctrl_putbytes.puBuffaddr = ttyut_inst_p->conv_tx_rx_buf + ttyut_inst_p->conv_tx_rx_wt_idx;
+                        ur_ctrl_putbytes.u2Length = ttyut_inst_p->conv_tx_rx_wrap
+                                                    ? (TTY_UT_LB_CON_TX_TX_BUF_SIZE - ttyut_inst_p->conv_tx_rx_wt_idx)
+                                                    : (ttyut_inst_p->conv_tx_rx_rd_idx - ttyut_inst_p->conv_tx_rx_wt_idx);
+
+                        if (ur_ctrl_putbytes.u2Length > 0
+                            && STATUS_OK == DclSerialPort_Control(handle, SIO_CMD_PUT_BYTES, (DCL_CTRL_DATA_T*) &ur_ctrl_putbytes)
+                            && ur_ctrl_putbytes.u2RetSize > 0)
+                        {
+                            ttyut_inst_p->conv_tx_rx_wt_idx += ur_ctrl_putbytes.u2RetSize;
+                            
+                            if (ttyut_inst_p->conv_tx_rx_wt_idx == TTY_UT_LB_CON_TX_TX_BUF_SIZE ) {
+                                /* reach the end of buffer, de-wrap to head */
+                                ASSERT(ttyut_inst_p->conv_tx_rx_wrap == 1);
+                                ttyut_inst_p->conv_tx_rx_wt_idx = 0;
+                                ttyut_inst_p->conv_tx_rx_wrap = 0;
+                                
+                                if (ttyut_inst_p->conv_tx_rx_rd_idx > 0) {
+                                    ur_ctrl_putbytes.u4OwenrId = ttyut_inst_p->owner;
+                                    ur_ctrl_putbytes.puBuffaddr = ttyut_inst_p->conv_tx_rx_buf;
+                                    ur_ctrl_putbytes.u2Length = ttyut_inst_p->conv_tx_rx_rd_idx - ttyut_inst_p->conv_tx_rx_wt_idx;
+                                    if (STATUS_OK == DclSerialPort_Control(handle, SIO_CMD_PUT_BYTES, (DCL_CTRL_DATA_T*) &ur_ctrl_putbytes)
+                                        && ur_ctrl_putbytes.u2RetSize > 0)
+                                    {
+                                        ttyut_inst_p->conv_tx_rx_wt_idx += ur_ctrl_putbytes.u2RetSize;
+                                    }
+                                }
+                            }
+                        }
+                    } else if (test_mode == TTY_UT_CONV_TX_ONLY || test_mode == TTY_UT_CONV_TX_NEW_RX) {
+                        if (ttyut_inst_p->ttyut_tx_len > 0)
+                        {                       
+                            ur_ctrl_putbytes.u4OwenrId = ttyut_inst_p->owner;
+                            ur_ctrl_putbytes.puBuffaddr = ttyut_inst_p->ttyut_tx_buf + ttyut_inst_p->ttyut_tx_offset;
+                            ur_ctrl_putbytes.u2Length = ttyut_inst_p->ttyut_tx_len;
+                            if (STATUS_OK == DclSerialPort_Control(handle, SIO_CMD_PUT_BYTES, (DCL_CTRL_DATA_T*) &ur_ctrl_putbytes))
+                            {                           
+                                ttyut_print("[TTY UT] send %d bytes data\r\n", ur_ctrl_putbytes.u2RetSize);
+                                ttyut_inst_p->ttyut_tx_len -= ur_ctrl_putbytes.u2RetSize;
+                                ttyut_inst_p->ttyut_tx_offset += ur_ctrl_putbytes.u2RetSize;
+                            }
+                        }
+                    }
+                }
+                break;
+            case MSG_ID_UART_READY_TO_READ_IND:
+                {
+                    UART_CTRL_GET_BYTES_T ur_ctrl_getbytes; 
+                    int idx;
+
+                    switch (test_mode)
+                    {
+                        case TTY_UT_CONV_TX_CONV_RX:
+                        case TTY_UT_NEW_INIT_CONV_TX_CONV_RX:
+                            {
+                                _tty_ut_conv_tx_conv_rx_rd_handler(handle);
+                            }
+                            break;
+                        case TTY_UT_NEW_TX_CONV_RX:
+                            {
+                                ur_ctrl_getbytes.u4OwenrId = ttyut_inst_p->owner;
+                                ur_ctrl_getbytes.puBuffaddr = ttyut_inst_p->ttyut_rx_buf;
+                                ur_ctrl_getbytes.u2Length = QBM_TTY_XXX_DATA_LEN;
+
+                                if (STATUS_OK == DclSerialPort_Control(handle, SIO_CMD_GET_BYTES, (DCL_CTRL_DATA_T*) &ur_ctrl_getbytes)
+                                        && ur_ctrl_getbytes.u2RetSize > 0)
+                                {
+                                    void *tx_gpd;
+                                    tty_io_request_t *tx_ior;
+                                    unsigned char *tx_buf_ptr;
+
+                                    tx_gpd = QBM_ALLOC_ONE(QBM_TYPE_TTY_TYPE1);
+                                    if (tx_gpd) {
+                                        tx_ior = (tty_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;
+                                        
+                                        tx_buf_ptr = QBM_DES_GET_DATAPTR(tx_gpd);
+                                        kal_mem_cpy((void*)tx_buf_ptr, ur_ctrl_getbytes.puBuffaddr, ur_ctrl_getbytes.u2RetSize);
+                                        QBM_DES_SET_DATALEN(tx_gpd, ur_ctrl_getbytes.u2RetSize); // Set data length
+                                        QBM_DES_SET_HWO(tx_gpd);
+                                        qbm_cal_set_checksum(tx_gpd);
+                                        //QBM_CACHE_FLUSH(tx_gpd, sizeof(qbm_gpd));
+
+                                        ttyut_print("[TTY UT] Receive data and re-send to Host, len=%d\r\n", ur_ctrl_getbytes.u2RetSize);
+                                        DclSerialPort_UpModuleTransmit(handle, tx_ior);
+                                    } else {
+                                        ttyut_print("[ERROR] [TTY UT] GPD allocate failed in QBM_TYPE_TTY_TYPE1 type\r\n");
+                                        ASSERT(tx_gpd);
+                                    }
+                                }
+                            }
+                            break;
+                        case TTY_UT_CONV_RX_ONLY:
+                            {
+                                ur_ctrl_getbytes.u4OwenrId = ttyut_inst_p->owner;
+                                ur_ctrl_getbytes.puBuffaddr = ttyut_inst_p->ttyut_rx_buf;
+                                ur_ctrl_getbytes.u2Length = TTY_UT_CONV_BUF_SIZE;
+                                
+                                if (STATUS_OK == DclSerialPort_Control(handle, SIO_CMD_GET_BYTES, (DCL_CTRL_DATA_T*) &ur_ctrl_getbytes)
+                                        && ur_ctrl_getbytes.u2RetSize > 0)
+                                {                               
+                                    ttyut_print("[TTY UT] Rx Only Test, len=%d, data: ", ur_ctrl_getbytes.u2RetSize);
+                                    for (idx = 0; idx < ur_ctrl_getbytes.u2RetSize; idx ++) {
+                                        ttyut_print("%c", ur_ctrl_getbytes.puBuffaddr[idx]);
+                                    }
+                                    ttyut_print("\r\n");
+                                }                               
+                            }
+                            break;
+                        default:
+                            break;
+                    }
+                }
+                break;
+            default:
+                break;
+        }
+    }
+}
+
+static void ttyut_test(tty_ut_mode_e test_mode, kal_uint8 uart_port)
+{
+    ilm_struct current_ilm = {0};
+    DCL_HANDLE handle;
+    ttyut_instance_t *ttyut_inst_p;
+    UART_CTRL_GET_DRV_STATE_T getDrvState;
+    DCL_UINT32 owner = MOD_NIL;
+    DCL_STATUS status;
+
+    handle = DclSerialPort_Open(uart_port, 0);
+    ttyut_inst_p = ttyut_get_instance(handle);
+    ASSERT(ttyut_inst_p);
+
+    // Wait for device ready
+    if (TTY_UT_COM1 == uart_port) {
+        owner = MOD_TTY_UT;
+    } else if (TTY_UT_COM2 == uart_port) {
+        owner = MOD_TTY_UT2;
+    } else if (TTY_UT_COM3 == uart_port) {
+        owner = MOD_TTY_UT3;
+    } else {
+        // Unsupported mode, ASSERT.
+        ASSERT(0);
+    }
+    getDrvState.u4OwnerId = owner;
+    do {
+        kal_sleep_task(KAL_TICKS_100_MSEC);
+        status = DclSerialPort_Control(handle, TTY_CMD_GET_DRV_STATE, (DCL_CTRL_DATA_T*) &getDrvState);
+    } while ((getDrvState.drv_state != DRV_ST_ATTACHED) || (status != STATUS_OK));
+
+
+    switch (test_mode)
+    {
+        case TTY_UT_BYPASS:
+            {
+                while(1)
+                {
+                    //do nothing;
+                    kal_sleep_task(KAL_TICKS_1_MIN);
+                }
+            }
+        case TTY_UT_CONV_TX_CONV_RX:
+            ttyut_print("[TTY UT] loopback Test of conventional Tx and conventional Rx - in Old init procedure\r\n");
+            {
+                while (1)
+                {
+                    while (msg_get_extq_messages() > 0)
+                    {
+                        if (msg_receive_extq(&current_ilm) == KAL_TRUE)
+                        {
+                            _ttyut_process_ilm(handle, &current_ilm, test_mode);
+                            destroy_ilm(&current_ilm);
+                        }
+                    }
+
+                    /* Polling Read */
+                    kal_sleep_task(KAL_TICKS_10_MSEC/10);
+                    _tty_ut_conv_tx_conv_rx_rd_handler(handle);
+                }
+            }
+            break;
+
+        case TTY_UT_NEW_INIT_CONV_TX_CONV_RX:
+            ttyut_print("[TTY UT] loopback Test of conventional Tx and conventional Rx - in New init procedure\r\n");
+            {
+                while (1)
+                {
+                    while (msg_get_extq_messages() > 0)
+                    {
+                        if (msg_receive_extq(&current_ilm) == KAL_TRUE)
+                        {
+                            _ttyut_process_ilm(handle, &current_ilm, test_mode);
+                            destroy_ilm(&current_ilm);
+                        }
+                    }
+
+                    /* Polling Read */
+                    kal_sleep_task(KAL_TICKS_10_MSEC/10);
+                    _tty_ut_conv_tx_conv_rx_rd_handler(handle);
+                }
+            }
+            break;
+
+        case TTY_UT_NEW_TX_CONV_RX:
+            ttyut_print("[TTY UT] loopback Test of new Tx and conventional Rx\r\n");
+            {
+                while (1)
+                {
+                    if (msg_receive_extq(&current_ilm) == KAL_TRUE)
+                    {
+                        _ttyut_process_ilm(handle, &current_ilm, test_mode);
+                        destroy_ilm(&current_ilm);
+                    }
+                }
+            }
+            break;
+
+        case TTY_UT_CONV_RX_ONLY:
+            ttyut_print("[TTY UT] conventional Rx Only Test\r\n");
+            {
+                while (1)
+                {
+                    if (msg_receive_extq(&current_ilm) == KAL_TRUE)
+                    {
+                        _ttyut_process_ilm(handle, &current_ilm, test_mode);
+                        destroy_ilm(&current_ilm);
+                    }
+                }
+            }
+            break;
+
+        case TTY_UT_NEW_RX_ONLY:
+            ttyut_print("[TTY UT] new Rx Only Test\r\n");
+            {
+                while (1)
+                {
+                    tty_io_request_t *rx_ior;
+                    unsigned char *rx_buf_ptr;
+                    int rx_buf_len;
+                    int idx;
+
+                    kal_take_mutex(ttyut_inst_p->ttyut_mutex);
+                    
+                    if (ttyut_inst_p->ttyut_rx_ior) {
+                        rx_ior = ttyut_inst_p->ttyut_rx_ior;
+                        ttyut_inst_p->ttyut_rx_ior = ttyut_inst_p->ttyut_rx_ior->next_request;
+                        kal_give_mutex(ttyut_inst_p->ttyut_mutex);
+                        rx_ior->next_request = NULL;
+
+                        /* Assert if first gpd is not equal to last gpd, unless Clear Rx/Set owner/Close command is requested */
+                        ASSERT(rx_ior->first_gpd == rx_ior->last_gpd);
+                        
+                        rx_buf_ptr = QBM_DES_GET_DATAPTR(rx_ior->first_gpd);
+                        rx_buf_len = QBM_DES_GET_DATALEN(rx_ior->first_gpd);
+                        QBM_CACHE_INVALID(rx_buf_ptr, rx_buf_len);
+                        
+                        ttyut_print("[TTY UT] Rx Only Test, len=%d, data: ", rx_buf_len);
+                        for (idx = 0; idx < rx_buf_len; idx ++) {
+                            ttyut_print("%c", rx_buf_ptr[idx]);
+                        }
+                        ttyut_print("\r\n");
+                        
+                        QBM_DES_SET_HWO(rx_ior->first_gpd);
+                        qbm_cal_set_checksum(rx_ior->first_gpd);
+                        QBM_CACHE_FLUSH(rx_ior->first_gpd, sizeof(qbm_gpd));    
+                        
+                        /* Re-assign this rx ior to driver for the following receiving */
+                        DclSerialPort_UpModuleAssignRxIor(handle, rx_ior);
+                    } else {
+                        kal_give_mutex(ttyut_inst_p->ttyut_mutex);
+                    }
+                    
+                    /* TODO: check scheduling/priority issue */
+                    kal_sleep_task(KAL_TICKS_10_MSEC);
+                    
+                    /* msg_receive_extq will block, therefore we poll if any message first */
+                    while (msg_get_extq_messages() > 0)
+                    {
+                        if (msg_receive_extq(&current_ilm) != KAL_TRUE)
+                        {
+                            break;
+                        }
+                        destroy_ilm(&current_ilm);
+                    }
+                }
+            }
+            break;
+        case TTY_UT_CONV_TX_ONLY:
+            kal_sleep_task(KAL_TICKS_3_SEC);
+            ttyut_print("[TTY UT] conventional Tx Only Test\r\n");
+            {
+                int idx, len;
+                DCL_STATUS ret_st;
+                
+                for (idx = 0; idx < TTY_UT_CONV_BUF_SIZE; idx ++) {
+                    ttyut_inst_p->ttyut_tx_buf[idx] = 'a' + idx % ('z'-'a'+1);
+                }
+                /* 1st round - 1~2048 bytes in order */
+                for (len = 1; len <= 2048; len ++) {
+                    UART_CTRL_PUT_BYTES_T ur_ctrl_putbytes;
+
+                    ttyut_print("[TTY UT] expect send %d bytes data\r\n", len);
+
+                    ttyut_inst_p->ttyut_tx_offset = 0;
+                    ttyut_inst_p->ttyut_tx_len = len;
+                    ur_ctrl_putbytes.u4OwenrId = ttyut_inst_p->owner;
+                    ur_ctrl_putbytes.puBuffaddr = ttyut_inst_p->ttyut_tx_buf;
+                    ur_ctrl_putbytes.u2Length = len;
+                    ret_st = DclSerialPort_Control(handle, SIO_CMD_PUT_BYTES, (DCL_CTRL_DATA_T*) &ur_ctrl_putbytes);
+
+                    if (STATUS_OK == ret_st && ur_ctrl_putbytes.u2RetSize > 0) {
+
+                        ttyut_print("[TTY UT] send %d bytes data\r\n", ur_ctrl_putbytes.u2RetSize);
+                        
+                        ttyut_inst_p->ttyut_tx_offset = ur_ctrl_putbytes.u2RetSize;
+                        ttyut_inst_p->ttyut_tx_len -= ur_ctrl_putbytes.u2RetSize;
+                    }
+
+                    kal_sleep_task(KAL_TICKS_10_MSEC);
+
+                    /* Polling ttyut_tx_len until all tx buffer are sent */
+                    while (ttyut_inst_p->ttyut_tx_len != 0)
+                    {
+                        kal_sleep_task(KAL_TICKS_10_MSEC/10);
+                        
+                        while (msg_get_extq_messages() > 0)
+                        {
+                            if (msg_receive_extq(&current_ilm) != KAL_TRUE) {
+                                break;
+                            } else {
+                                _ttyut_process_ilm(handle, &current_ilm, test_mode);
+                            }
+                            destroy_ilm(&current_ilm);
+                        }
+                    }
+
+                }
+
+                /* 2nd round - 1~2048 bytes in random size */
+                while (1)
+                {
+                    UART_CTRL_PUT_BYTES_T ur_ctrl_putbytes;
+                    
+                    len = rand()%TTY_UT_CONV_BUF_SIZE + 1;
+                    ur_ctrl_putbytes.u4OwenrId = ttyut_inst_p->owner;
+                    ur_ctrl_putbytes.puBuffaddr = ttyut_inst_p->ttyut_tx_buf;
+                    ur_ctrl_putbytes.u2Length = len;                    
+                    ttyut_inst_p->ttyut_tx_offset = 0;
+                    ttyut_inst_p->ttyut_tx_len = len;
+                    ret_st = DclSerialPort_Control(handle, SIO_CMD_PUT_BYTES, (DCL_CTRL_DATA_T*) &ur_ctrl_putbytes);
+
+                    if (STATUS_OK == ret_st && ur_ctrl_putbytes.u2RetSize > 0)
+                    {
+                        ttyut_print("[TTY UT] send %d bytes data\r\n", ur_ctrl_putbytes.u2RetSize);
+                        
+                        ttyut_inst_p->ttyut_tx_offset = ur_ctrl_putbytes.u2RetSize;
+                        ttyut_inst_p->ttyut_tx_len -= ur_ctrl_putbytes.u2RetSize;
+                    }
+
+                    /* Polling ttyut_tx_len until all tx buffer are sent */
+                    while (ttyut_inst_p->ttyut_tx_len != 0)
+                    {
+                        kal_sleep_task(KAL_TICKS_10_MSEC);
+                        
+                        while (msg_get_extq_messages() > 0)
+                        {
+                            if (msg_receive_extq(&current_ilm) != KAL_TRUE) {
+                                break;
+                            } else {
+                                _ttyut_process_ilm(handle, &current_ilm, test_mode);
+                            }
+                            destroy_ilm(&current_ilm);
+                        }
+                    }
+                } /* while */
+            }
+
+            break;
+        case TTY_UT_NEW_TX_ONLY:
+            kal_sleep_task(KAL_TICKS_3_SEC);
+            ttyut_print("[TTY UT] new Tx Only Test\r\n");
+            {
+                int idx;
+                for (idx = 0; idx < TTY_UT_NEW_BUF_SIZE; idx ++) {
+                    ttyut_inst_p->ttyut_tx_buf[idx] = 'a' + idx % ('z'-'a'+1);
+                }
+                while (1)
+                {
+                    void *tx_gpd;
+                    tty_io_request_t *tx_ior;
+                    unsigned char *tx_buf_ptr;
+
+                    tx_gpd = QBM_ALLOC_ONE(QBM_TYPE_TTY_TYPE1);
+                    if (tx_gpd) {
+                        tx_ior = (tty_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;
+                        ttyut_inst_p->ttyut_tx_len = rand()%TTY_UT_NEW_BUF_SIZE + 1;
+                        
+                        tx_buf_ptr = QBM_DES_GET_DATAPTR(tx_gpd);
+                        kal_mem_cpy((void*)tx_buf_ptr, ttyut_inst_p->ttyut_tx_buf, ttyut_inst_p->ttyut_tx_len);
+                        QBM_DES_SET_DATALEN(tx_gpd, ttyut_inst_p->ttyut_tx_len); // Set data length
+                        QBM_DES_SET_HWO(tx_gpd);
+                        qbm_cal_set_checksum(tx_gpd);
+                        //QBM_CACHE_FLUSH(tx_gpd, sizeof(qbm_gpd));
+
+                        ttyut_print("[TTY UT] send %d bytes data\r\n", ttyut_inst_p->ttyut_tx_len);
+                        DclSerialPort_UpModuleTransmit(handle, tx_ior);
+                    } else {
+                        ttyut_print("[ERROR] [TTY UT] GPD allocate failed in QBM_TYPE_TTY_TYPE1 type\r\n");
+                    }
+                    
+                    /* TODO: check scheduling/priority issue */
+                    kal_sleep_task(KAL_TICKS_10_MSEC);
+                    
+                    /* msg_receive_extq will block, therefore we poll if any message first */
+                    while (msg_get_extq_messages() > 0)
+                    {
+                        if (msg_receive_extq(&current_ilm) != KAL_TRUE)
+                        {
+                            break;
+                        }
+                        destroy_ilm(&current_ilm);
+                    }
+                }
+            }
+            break;
+        case TTY_UT_NEW_TX_NEW_RX:
+            ttyut_print("[TTY UT] loopback Test of new Tx and new Rx\r\n");
+            {
+                while (1)
+                {
+                    void *tx_gpd;
+                    tty_io_request_t *tx_ior;
+                    tty_io_request_t *rx_ior;
+                    unsigned char *tx_buf_ptr;
+                    unsigned char *rx_buf_ptr;
+                    kal_uint16 rx_len;
+
+                    kal_take_mutex(ttyut_inst_p->ttyut_mutex);
+                    
+                    if (ttyut_inst_p->ttyut_rx_ior)
+                    {
+                        rx_ior = ttyut_inst_p->ttyut_rx_ior;
+                        ttyut_inst_p->ttyut_rx_ior = ttyut_inst_p->ttyut_rx_ior->next_request;
+                        kal_give_mutex(ttyut_inst_p->ttyut_mutex);
+                        rx_ior->next_request = NULL;
+
+                        /* Assert if first gpd is not equal to last gpd, unless Clear Rx/Set owner/Close command is requested */
+                        ASSERT(rx_ior->first_gpd == rx_ior->last_gpd);
+                        
+                        tx_gpd = QBM_ALLOC_ONE(QBM_TYPE_TTY_TYPE1);
+                        if (tx_gpd) {
+                            tx_ior = (tty_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;
+                            
+                            tx_buf_ptr = QBM_DES_GET_DATAPTR(tx_gpd);
+                            rx_buf_ptr = QBM_DES_GET_DATAPTR(rx_ior->first_gpd);
+                            rx_len = QBM_DES_GET_DATALEN(rx_ior->first_gpd);
+
+                            QBM_CACHE_INVALID(rx_buf_ptr, rx_len);
+                            kal_mem_cpy((void*)tx_buf_ptr, (void*)rx_buf_ptr, rx_len);
+                            QBM_CACHE_FLUSH(tx_buf_ptr, rx_len); // flush tx data
+                            
+                            QBM_DES_SET_DATALEN(tx_gpd, rx_len); // Set data length
+                            QBM_DES_SET_HWO(tx_gpd);
+                            qbm_cal_set_checksum(tx_gpd);
+                            QBM_CACHE_FLUSH(tx_gpd, sizeof(qbm_gpd));
+
+                            ttyut_print("[TTY UT] Receive data and re-send to Host, len=%d\r\n", rx_len);
+                            DclSerialPort_UpModuleTransmitLight(handle, tx_ior);
+                        } else {
+                            ttyut_print("[ERROR] [TTY UT] GPD allocate failed in QBM_TYPE_TTY_TYPE1 type\r\n");
+                        }
+                        
+                        QBM_DES_SET_HWO(rx_ior->first_gpd);
+                        qbm_cal_set_checksum(rx_ior->first_gpd);
+                        QBM_CACHE_FLUSH(rx_ior->first_gpd, sizeof(qbm_gpd));    
+
+                        /* Re-assign this rx ior to driver for the following receiving */
+                        DclSerialPort_UpModuleAssignRxIor(handle, rx_ior);
+                    } else {
+                        kal_give_mutex(ttyut_inst_p->ttyut_mutex);
+                    }
+                    
+                    /* TODO: check scheduling/priority issue */
+                    kal_sleep_task(KAL_TICKS_10_MSEC);
+                    
+                    /* msg_receive_extq will block, therefore we poll if any message first */
+                    while (msg_get_extq_messages() > 0)
+                    {
+                        if (msg_receive_extq(&current_ilm) != KAL_TRUE)
+                        {
+                            break;
+                        }
+                        destroy_ilm(&current_ilm);
+                    }
+                }
+            }
+            break;
+        case TTY_UT_CONV_TX_NEW_RX:
+            ttyut_print("[TTY UT] loopback Test of conventional Tx and new Rx\r\n");
+            {
+                while (1)
+                {
+                    UART_CTRL_PUT_BYTES_T ur_ctrl_putbytes;
+                    tty_io_request_t *rx_ior;
+                    void *rx_data;
+                    kal_uint16 rx_len;
+
+                    kal_take_mutex(ttyut_inst_p->ttyut_mutex);
+                    
+                    if (ttyut_inst_p->ttyut_rx_ior)
+                    {
+                        rx_ior = ttyut_inst_p->ttyut_rx_ior;
+                        ttyut_inst_p->ttyut_rx_ior = ttyut_inst_p->ttyut_rx_ior->next_request;
+                        kal_give_mutex(ttyut_inst_p->ttyut_mutex);
+                        rx_ior->next_request = NULL;
+
+                        /* Assert if first gpd is not equal to last gpd, unless Clear Rx/Set owner/Close command is requested */
+                        ASSERT(rx_ior->first_gpd == rx_ior->last_gpd);
+
+                        rx_data = QBM_DES_GET_DATAPTR(rx_ior->first_gpd);
+                        rx_len = QBM_DES_GET_DATALEN(rx_ior->first_gpd);
+
+                        if (rx_len > 0)
+                        {   /* in the test case, only one gpd is used in one ior since we only send 2 gpds to driver and one is for tailing */
+                            QBM_CACHE_INVALID(rx_data, rx_len);
+                            ASSERT(rx_len <= QBM_TTY_XXX_DATA_LEN);
+                            kal_mem_cpy(ttyut_inst_p->ttyut_tx_buf, rx_data, rx_len);
+                            ttyut_inst_p->ttyut_tx_len = rx_len;
+                            
+                            ur_ctrl_putbytes.u4OwenrId = ttyut_inst_p->owner;
+                            ur_ctrl_putbytes.puBuffaddr = ttyut_inst_p->ttyut_tx_buf;
+                            ur_ctrl_putbytes.u2Length = ttyut_inst_p->ttyut_tx_len;
+
+                            if (STATUS_OK == DclSerialPort_Control(handle, SIO_CMD_PUT_BYTES, (DCL_CTRL_DATA_T*) &ur_ctrl_putbytes)
+                                && ur_ctrl_putbytes.u2RetSize < ttyut_inst_p->ttyut_tx_len)
+                            {
+                                ttyut_inst_p->ttyut_tx_offset = ur_ctrl_putbytes.u2RetSize;
+                                ttyut_inst_p->ttyut_tx_len -= ur_ctrl_putbytes.u2RetSize;
+                            }
+                        }
+
+                        QBM_DES_SET_HWO(rx_ior->first_gpd);
+                        QBM_DES_SET_NEXT(rx_ior->first_gpd, NULL);
+                        qbm_cal_set_checksum(rx_ior->first_gpd);
+                        QBM_CACHE_FLUSH(rx_ior->first_gpd, sizeof(qbm_gpd));    
+
+                        /* Re-assign this rx ior to driver for the following receiving */
+                        DclSerialPort_UpModuleAssignRxIor(handle, rx_ior);
+                    } else {
+                        kal_give_mutex(ttyut_inst_p->ttyut_mutex);
+                    }
+                    
+                    /* TODO: check scheduling/priority issue */
+                    kal_sleep_task(KAL_TICKS_10_MSEC);
+                    
+                    /* msg_receive_extq will block, therefore we poll if any message first */
+                    while (msg_get_extq_messages() > 0)
+                    {
+                        if (msg_receive_extq(&current_ilm) != KAL_TRUE) {
+                            break;
+                        } else {
+                            _ttyut_process_ilm(handle, &current_ilm, test_mode);
+                        }
+                        destroy_ilm(&current_ilm);
+                    }
+                }
+            }
+            break;
+        default:
+            break;
+    }
+}
+
+
+// ==========================================================
+// TTY_UT Task Function
+// ==========================================================
+kal_uint32 ttyut_tsk_num=0;
+kal_spinlockid ttyut_tsk_pri_spl;
+kal_taskid tty_tsk_pri[TTY_UT_COM_NUM];
+kal_uint32 ttyut_get_current_task_priority()
+{
+    kal_uint32 tty_pri, tty_ist=ttyut_tsk_num;
+    kal_taskid tskp=kal_get_current_task();
+    ASSERT(tskp);
+    kal_take_spinlock(ttyut_tsk_pri_spl, KAL_INFINITE_WAIT);
+    for(tty_pri=0;tty_pri<ttyut_tsk_num&&tty_tsk_pri[tty_pri]!=tskp;tty_pri++) tty_ist=tty_ist==ttyut_tsk_num&&!tty_tsk_pri[tty_pri]?tty_pri:tty_ist;
+    if(tty_pri==ttyut_tsk_num&&tty_ist<ttyut_tsk_num) tty_tsk_pri[tty_pri=tty_ist]=tskp;
+    kal_give_spinlock(ttyut_tsk_pri_spl);
+    return tty_pri==ttyut_tsk_num?0:tty_pri+1;
+}
+
+kal_bool ttyut_task_init(void)
+{
+    if(ttyut_tsk_num==0) ttyut_tsk_pri_spl=kal_create_spinlock("TTYUT_TSK_SPL");
+    tty_tsk_pri[ttyut_tsk_num++]=NULL;
+
+    // Init ttyut instance struct.
+    kal_mem_set(&ttyut_inst_g, 0, sizeof(ttyut_inst_g));
+
+    return KAL_TRUE;
+}
+
+static void ttyut_task_main(task_entry_struct *task_entry_ptr)
+{
+    kal_uint32 tsk_pri;
+    kal_bool ret = KAL_TRUE;
+
+    tsk_pri = ttyut_get_current_task_priority();
+
+#if TTY_UT_MISC_TEST
+    DCL_STATUS status;
+    DCL_HANDLE handle;
+    UART_CTRL_GET_DRV_STATE_T getDrvState;
+    /*Init test and change owner test*/
+    if (TTY_UT_TASK_1_PRIORITY == tsk_pri) {
+        // Init_deinit test
+        kal_set_active_module_id(MOD_TTY_UT);
+
+        /*Make sure driver is already attached*/
+        handle = DclSerialPort_Open(TTY_UT_COM1, 0);
+        getDrvState.u4OwnerId = MOD_TTY_UT;
+        do {
+            kal_sleep_task(KAL_TICKS_100_MSEC);
+            status = DclSerialPort_Control(handle, TTY_CMD_GET_DRV_STATE, (DCL_CTRL_DATA_T*) &getDrvState);
+        } while ((getDrvState.drv_state != DRV_ST_ATTACHED) || (status != STATUS_OK)); 
+
+        if (_ttyut_upmod_init_deinit_test(TTY_UT_COM1)) {
+            ttyut_print("[TTY UT] init-deinit test OK\r\n");
+        } else {
+            ttyut_print("[TTY UT] init-deinit test failed\r\n");
+            //return;
+            ASSERT(0);
+        }
+
+        // Change_owner test
+        if (_ttyut_upmod_change_owner_test()) {
+            ttyut_print("[TTY UT] change owner test OK\r\n");
+        } else {
+            ttyut_print("[TTY UT] change owner test failed\r\n");
+            //return;
+            ASSERT(0);
+        }
+    }
+#endif
+
+    /*
+     * S1.TTYUT_PREPROC.
+     */
+    switch (tsk_pri)
+    {
+        case TTY_UT_TASK_1_PRIORITY:
+            kal_set_active_module_id(MOD_TTY_UT);
+            ret = ttyut_test_preproc(tty_ut_mode_1, TTY_UT_COM1);
+            break;
+
+        case TTY_UT_TASK_2_PRIORITY:
+            if (TTY_UT_COM_NUM > 1) {
+                kal_set_active_module_id(MOD_TTY_UT2);
+                ret = ttyut_test_preproc(tty_ut_mode_2, TTY_UT_COM2);
+            }
+            break;
+
+        case TTY_UT_TASK_3_PRIORITY:
+            if (TTY_UT_COM_NUM > 2) {
+                kal_set_active_module_id(MOD_TTY_UT3);
+                ret = ttyut_test_preproc(tty_ut_mode_3, TTY_UT_COM3);
+            }
+            break;
+
+        default:
+            // Unsupported mode, ASSERT.
+            ASSERT(0);
+            break;
+    }
+
+    if (KAL_TRUE == ret) {
+
+    } else {
+        // Failed to ttyut_test_preproc(), ASSERT.
+        ASSERT(0);
+    }
+
+    /*
+     * S2. TTYUT_MAIN.
+     */
+    switch (tsk_pri)
+    {
+        case TTY_UT_TASK_1_PRIORITY:
+
+            ttyut_test(tty_ut_mode_1, TTY_UT_COM1);
+            break;
+
+        case TTY_UT_TASK_2_PRIORITY:
+            if (TTY_UT_COM_NUM > 1) {
+                ttyut_test(tty_ut_mode_2, TTY_UT_COM2);
+            }
+            break;
+
+        case TTY_UT_TASK_3_PRIORITY:
+            if (TTY_UT_COM_NUM > 2) {
+                ttyut_test(tty_ut_mode_3, TTY_UT_COM3);
+            }
+            break;
+
+        default:
+            // Unsupport mode, ASSERT.
+            ASSERT(0);
+            break;
+    }
+
+    while (1) {
+        kal_sleep_task(KAL_TICKS_30_SEC);
+    }
+}
+
+kal_bool ttyut_create(comptask_handler_struct **handle)
+{
+    static const comptask_handler_struct ttyut_handler_info =
+    {
+        ttyut_task_main,        /* task entry function */
+        ttyut_task_init,        /* task initialization function */
+        NULL                    /* task reset handler */
+    };
+
+    ttyut_print("=========>ttyut_create\r\n");
+
+    *handle = (comptask_handler_struct *)&ttyut_handler_info;
+    return KAL_TRUE;
+}
+