blob: 604ab336fa4fa5624ea36b91f8063aab24892efb [file] [log] [blame]
/*****************************************************************************
* 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:
* ---------
* cccidev_qbm.h
*
* Project:
* --------
* MOLY
*
* Description:
* ------------
* Defines the common qmu_bm macros or inline functions for CCCI devices
*
* Author:
* -------
* -------
*
* ==========================================================================
* $Log$
*
* 09 18 2020 li-cheng.tsai
* [MOLY00569647] [MP7.PRECHECKIN.DEV][Code sync] sync code from T700
* [R3.MP][OA][CCCI]code sync from T700
*
* 09 15 2020 li-cheng.tsai
* [MOLY00569647] [MP7.PRECHECKIN.DEV][Code sync] sync code from T700
* [MP7.PRECHECKIN.DEV][OA][CCCI]code sync from T700
*
* 08 04 2020 actory.ou
* [MOLY00554534] [Colgin][Code sync] sync code from MT6880.MP
* [T700][OA][CCCI] sync from MT6880
*
* 07 07 2020 actory.ou
* [MOLY00543186] [Colgin] code sync to NR15.R3.MT6880.MP
* [R3.MT6880.MP][OA][CCCI] sync from COLGIN.SB.SMT.DEV
*
* 05 19 2020 actory.ou
* [MOLY00525599] code sync for Colgin
* [NR15.R3.COLGIN.SB.SMT.DEV][OA][CCCI] code sync from 19NOV
*
* 12 18 2019 actory.ou
* [MOLY00465742] [Gen97] add L5 channels and change CCIF SHM layout
* [19NOV.DEV][OA] add L5 channels
*
* 09 15 2017 chien-hui.lu
* [MOLY00278317] [CCCI][LHIFCORE][CCISMCORE] Performance improvement of INT_QueryExceptionStatus
* [CCCI][LHIFCORE][CCISMCORE] Performance improvement of INT_QueryExceptionStatus.
*
* 08 01 2017 chien-hui.lu
* [MOLY00260287] MD CCCI add cache API enhance to LR12 trunk
* [CCCI] cache API enhancement and aggregation, porting from UMOLY.
*
* 11 08 2016 cs.huang
* [MOLY00204430] [CCCI] MT6293 change
* [CCCI] Fast CCCI header problem
*
* 08 15 2016 cs.huang
* [MOLY00197453] [CCCI] Fast CCCI header change SPD header size
* [CCCI] Fast CCCI header problem
*
* 06 07 2016 cs.huang
* [MOLY00183140] [Coverity Scanned Code Defect]CID:138824 code defect happened in /mcu/common/interface/service/hif/cccidev_qbm.h
* [CCCI] Fix coverity warning
* 06 01 2016 cs.huang
* [MOLY00182647] [CCCI] Fast CCCI header
* [CCCI] Fast CCCI header
*
* 06 01 2016 cs.huang
* [MOLY00182647] [CCCI] Fast CCCI header
* [CCCI] Fast CCCI header
*
* 12 28 2015 cs.huang
* [MOLY00155074] [CCCI] Fix CCCI header length for TTY and fix IT program
* [CCCI] Fix CCCI header length for TTY and fix IT program
*
* 12 28 2015 cs.huang
* [MOLY00155074] [CCCI] Fix CCCI header length for TTY and fix IT program
* [CCCI] Fix CCCI header length for TTY and fix IT program
* 08 07 2015 cs.huang
* [MOLY00136043] cccidev_qbm.h assertion
* [CCMNI] Fix SPD EOL problem
*
*
* 08 07 2015 cs.huang
* [MOLY00136043] cccidev_qbm.h assertion
* [CCMNI] Fix SPD EOL problem
*
* 08 06 2015 cs.huang
* [MOLY00135464] [CCCI] New CCCI handshake flow
* [CCCI] New CCCI handshake flow
*
* 08 06 2015 cs.huang
* [MOLY00135464] [CCCI] New CCCI handshake flow
* [CCCI] New CCCI handshake flow
* 07 28 2015 cs.huang
* [MOLY00131268] [CCMNI] Add SPD trace
* [CCMNI] Add SPD trace
*
* 07 28 2015 cs.huang
* [MOLY00131268] [CCMNI] Add SPD trace
* [CCMNI] Add SPD trace
*
* 07 24 2015 cs.huang
* [MOLY00131268] [CCMNI] Add SPD trace
* [CCMNI] Add SPD trace timing
*
* 07 23 2015 cs.huang
* [MOLY00131268] [CCMNI] Add SPD trace
* [CCMNI] Add SPD trace
*
* 05 08 2015 cs.huang
* [MOLY00112001] [CCCI] Change CCCI sequence definition in CCCI header.
* [CCCI] Change CCCI sequence definition in CCCI header.
*
* 05 05 2015 cs.huang
* [MOLY00111097] [CCCI] Modify RMPU buffer definition
* [CCCI] Modify polling buffer defination for RMPU
*
* 04 15 2015 i-wei.tsai
* [MOLY00107626] [TK6291][CCCITTY] enable sequence check and exception SPD support
* .
*
* 03 27 2015 ap.wang
* [MOLY00100246] [UMOLY] Fix SPD type3 re-layout error
* Add CCCI Len for SPD DL v2
*
* 03 24 2015 ap.wang
* [MOLY00100246] [UMOLY] Fix SPD type3 re-layout error
* .
*
* 01 23 2015 ap.wang
* [MOLY00092900] [UMOLY] L2 Copro zero len packet on SPD
* .
*
* 12 10 2014 cs.huang
* [MOLY00080351] [MT6291][CCCI] Add L1Core CCCI service (CCCI SYSMSG/RPC/IPC)
* [CCCI] PCore/L1Core CCCI enhancement
*
* 11 13 2014 cs.huang
* [MOLY00084049] [CCCI] Merging P2P CCCI related change
* Merging
*
* //UMOLY/DEV/MT6291_DEV/mcu/pcore/...
*
* to //UMOLY/TRUNK/UMOLY/mcu/pcore/...
*
* 11 13 2014 cs.huang
* [MOLY00081425] [TK6291_DEV] Add SPD sw solution
* Merging
*
* //UMOLY/DEV/MT6291_DEV/mcu/pcore/...
*
* to //UMOLY/TRUNK/UMOLY/mcu/pcore/...
*
* 11 13 2014 cs.huang
* [MOLY00075481] Add CCCI SPD DL support
* Merging
*
* //UMOLY/DEV/MT6291_DEV/mcu/pcore/...
*
* to //UMOLY/TRUNK/UMOLY/mcu/pcore/...
*
*
*
* 08 14 2014 ap.wang
* [MOLY00075481] Add CCCI SPD DL support
* CCCIDEV SPD DL common process
* 07 22 2014 cs.huang
* [MOLY00071952] [CCCI] Add new CCCI debug mechanism (1. CCCI seq check 2. AP polling MD status)
* [CCCI] ccci new debug mechanism
*
* 07 22 2014 cs.huang
* [MOLY00071952] [CCCI] Add new CCCI debug mechanism (1. CCCI seq check 2. AP polling MD status)
* [CCCI] CCCI new debug mechanism
* 07 09 2014 cs.huang
* [MOLY00071904] [WW FT][4G Gemini][FT][HK][Offical][CSL+PCCW]Externel (EE),0,0,99,/data/core/,1,modem,md0:[ASSERT] file:ccci_rpc_data.c line:587
* [CCCI RPC] Fix ccci rpc coding defect in ccci_rpc_receive_cb
*
* 07 09 2014 cs.huang
* [MOLY00071904] [WW FT][4G Gemini][FT][HK][Offical][CSL+PCCW]Externel (EE),0,0,99,/data/core/,1,modem,md0:[ASSERT] file:ccci_rpc_data.c line:587
* [CCCI RPC] Fix ccci rpc coding defect in ccci_rpc_receive_cb
*
* 09 06 2013 ap.wang
* [MOLY00036761] [CCCI] Add L2 trace log [CCCI] Add L2 trace log
*
* 06 25 2013 ian.cheng
* [MOLY00027392] [CCCI]CCCIDEV_GET_QBM_DATALEN should return GPD.len for DHL
* [MOLY][CCCI] CCCIDEV_GET_QBM_DATALEN return GPD length even when there's BD
*
* 03 14 2013 ap.wang
* [MOLY00011922] [CCCIDEV] Add GPD cache flush after set checksum
* [CCCIDEV] Add GPD cache flush after set checksum
*
* 02 21 2013 i-wei.tsai
* [MOLY00010624] CCCITTY integartion test code revise
* remove internal _reset_ccci_common
*
* 02 04 2013 i-wei.tsai
* [MOLY00009892] Rename as MT6290
* Rename project name as MT6290
*
* 01 08 2013 i-wei.tsai
* [MOLY00008347] [MT6290] [CCCI] CCCI re-Architecture
* sync latest version of new features
*
* 12 06 2012 ian.cheng
* [MOLY00007169] [CCCI_SDIO] MOLY phase in
* [MOLY][CCCI_SDIO] 1st version of MT6290 CCCI feature
*
* 12 06 2012 ian.cheng
* [MOLY00007169] [CCCI_SDIO] MOLY phase in
* [MOLY][CCCI_SDIO] 1st version of MT6290 CCCI feature
****************************************************************************/
#ifndef _CCCIDEV_QBM_H
#define _CCCIDEV_QBM_H
#include "kal_public_api.h"
#include "qmu_bm.h"
#include "qmu_bm_util.h"
#include "ccci_if.h" /* ccci_io_request_t */
#include "hif_spd_ext.h"
#define CCCI_TTY_DEV_NUM (uart_port_ccci_end-uart_port_ccci_start+2) //+2 for uart_port_dhl_sp_expt and uart_port_dhl_ctrl_sp_expt
/*!
* @function [INLINE] CCCICOMM_SET_QBM_DATALEN
* @brief Set data length for QBM_TYPE_CCCI_COMM by QBM_DES_SET_DATALEN
*
* @param gpd [IN] pointer to the GPD
*
* @return void
*/
static __inline void CCCICOMM_SET_QBM_DATALEN(void* gpd, kal_uint32 data_len)
{
void* bd = NULL;
EXT_ASSERT(NULL != gpd, (kal_uint32)gpd, data_len, 0);
/*QBM_TYPE_CCCI_COMM specific function*/
EXT_ASSERT(QBM_TYPE_CCCI_COMM == QBM_GET_TYPE(gpd), (kal_uint32)QBM_GET_TYPE(gpd), (kal_uint32)gpd, data_len);
/*Must have BD*/
EXT_ASSERT(0 != QBM_DES_GET_BDP(gpd), (kal_uint32)QBM_DES_GET_BDP(gpd), (kal_uint32)gpd, data_len);
bd = QBM_DES_GET_DATAPTR(gpd);
EXT_ASSERT(NULL!=bd, (kal_uint32)gpd, (kal_uint32)bd, data_len);
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);
}
/*!
* @function [INLINE] CCCIDEV_GET_QBM_DATALEN
* @brief Obtain the data length of first BD in GPD list.
* Possible application is used during inserting layer headers ex. CCCI headers.
*
* @param gpd [IN] pointer to the GPD
*
* @return Return gpd->1st_bd->data_len / gpd->data_len
*/
static __inline kal_uint32 CCCIDEV_GET_QBM_DATALEN(void* gpd)
{
kal_uint32 data_len = 0;
EXT_ASSERT(NULL!=gpd, (kal_uint32) gpd,0 ,0);
/* user should put length in gpd.len
gpd.len = bd.ext_len + bd.len */
data_len = QBM_DES_GET_DATALEN(gpd);
return data_len;
}
#include <ex_public.h>
/*!
* @function [INLINE] CCCIDEV_GET_QBM_DATAPTR
* @brief Obtain the pointer of data.
*
* @param gpd [IN] pointer to the GPD
*
* @return Return gpd->1st_bd->p_data_tbd / gpd->p_data_tbd
*/
static __inline void* CCCIDEV_GET_QBM_DATAPTR(void* gpd)
{
void* bd = NULL;
void* data_ptr = NULL;
EXT_ASSERT(NULL!=gpd, (kal_uint32) gpd, 0, 0);
if(0 != QBM_DES_GET_BDP(gpd)){
//4 <case 1> GPD->BD->BUFF
bd = QBM_DES_GET_DATAPTR(gpd);
EXT_ASSERT(NULL!=bd, (kal_uint32) bd, (kal_uint32) gpd, 0);
data_ptr = QBM_DES_GET_DATAPTR(bd);
}else{
//4 <case 2> GPD->BUFF
data_ptr = QBM_DES_GET_DATAPTR(gpd);
}
//Note: This API is also used in exception mode
//In exception mode, DHL may directly dump memory address 0x0 (use 0x0 as data buffer address)
if(INT_QueryExceptionStatus() == KAL_FALSE)
{
EXT_ASSERT(NULL!=data_ptr, (kal_uint32) data_ptr, (kal_uint32) bd, (kal_uint32) gpd);
}
return data_ptr;
}
/*!
* @function [INLINE] CCCIDEV_GET_GPD_LIST_SIZE
* @brief Traverse the GPD chain to obtain the number of GPDs in GPD chain.
*
* @param head [IN] pointer to the head of the GPD chain
* @param tail [IN] pointer to the tail of the GPD chain
*
* @return Number of the GPDs in GPD chain.
*/
static __inline kal_uint32 CCCIDEV_GET_GPD_LIST_SIZE(qbm_gpd *head, qbm_gpd *tail)
{
kal_uint32 cnt = 0;
if (tail) {
while (head) {
cnt++;
if (head != tail) {
head = QBM_DES_GET_NEXT(head);
} else {
break;
}
}
}
return cnt;
}
/*!
* @function [INLINE] CCCIDEV_GET_NONBPS_GPD_LIST_SIZE
* @brief Traverse the GPD chain to obtain the number of NON-bypass GPDs in GPD chain.
*
* @param head [IN] pointer to the head of the GPD chain
* @param tail [IN] pointer to the tail of the GPD chain
*
* @return Number of the non-bypass GPDs in GPD chain.
*/
static __inline kal_uint32 CCCIDEV_GET_NONBPS_GPD_LIST_SIZE(qbm_gpd *head, qbm_gpd *tail)
{
kal_uint32 cnt = 0;
if (tail) {
while (head) {
cnt += (0 == QBM_DES_GET_BPS(head));
if (head != tail) {
head = QBM_DES_GET_NEXT(head);
} else {
break;
}
}
}
return cnt;
}
/*!
* @function [INLINE] CCCIDEV_PUSH_QBM_DATAHEAD
* @brief Push the Tx GPD/BD data pointer. i.e. increase the header room
* 1. move the GPD->1st_BD->data / GPD->data pointer back "offset"
* 2. increase the BD length
* 3. DO NOT flush the Tx BD header -> QMU enqueue should do it
* Please refer to the mail 20120606 from YiLun
* > Folder: 0WCP\0. important announce\programming related
* > [Note] CACHE op convention : upper user no need to take TX GPD/BD cache flush(clean)
* 4. set gpd data length
* 5. DO NOT flush the Tx GPD header -> QMU enqueue should do it
* reference : ETHC_CORE_PUSH_QBM_DATAHEAD
*
* @param gpd [IN] pointer to the GPD need modification
* @param offset [IN] move the data_ptr by offset
*
* @return void
*/
static __inline void CCCIDEV_PUSH_QBM_DATAHEAD(void* gpd, kal_uint32 offset)
{
void* bd = NULL;
kal_uint8* data_ptr = NULL;
kal_uint32 data_len = 0;
if(0 != QBM_DES_GET_BDP(gpd)){
//4 <case 1> GPD->BD->BUFF
/* set bd data ptr */
bd = QBM_DES_GET_DATAPTR(gpd);
data_ptr = (kal_uint8*)QBM_DES_GET_DATAPTR(bd);
QBM_DES_SET_DATAPTR(bd, data_ptr-offset);
/* set bd data len */
data_len = QBM_DES_GET_DATALEN(bd);
QBM_DES_SET_DATALEN(bd, data_len+offset);
/* set bd checksum */
qbm_cal_set_checksum(bd);
/* set gpd data len */
data_len = QBM_DES_GET_DATALEN(gpd);
QBM_DES_SET_DATALEN(gpd, data_len+offset);
/* set gpd checksum */
//qbm_cal_set_checksum(gpd);
}else{
//4 <case 2> GPD->BUFF
/* set gpd data ptr */
data_ptr = (kal_uint8*)QBM_DES_GET_DATAPTR(gpd);
QBM_DES_SET_DATAPTR(gpd, data_ptr-offset);
/* set gpd data len */
data_len = QBM_DES_GET_DATALEN(gpd);
QBM_DES_SET_DATALEN(gpd, data_len+offset);
/* set gpd checksum */
//qbm_cal_set_checksum(gpd);
}
}
/*!
* @function [INLINE] CCCIDEV_PULL_QBM_DATAHEAD
* @brief Pull the Tx GPD/BD data pointer. i.e. decrease the header room
*
* <Used in non-network GPD->BD->BUFF >
*
* @param gpd [IN] pointer to the GPD need modification
* @param offset [IN] move the data_ptr by offset
*
* @return void
*/
static __inline void CCCIDEV_PULL_QBM_DATAHEAD(void* gpd, kal_uint32 offset)
{
void* bd = NULL;
kal_uint8* data_ptr = NULL;
kal_uint32 data_len = 0;
if(0 != QBM_DES_GET_BDP(gpd)){
//4 <case 1> GPD->BD->BUFF
/* set bd data ptr */
bd = QBM_DES_GET_DATAPTR(gpd);
data_ptr = (kal_uint8*)QBM_DES_GET_DATAPTR(bd);
QBM_DES_SET_DATAPTR(bd, data_ptr+offset);
/* set bd data len */
data_len = QBM_DES_GET_DATALEN(bd);
QBM_DES_SET_DATALEN(bd, data_len-offset);
/* set bd checksum */
qbm_cal_set_checksum(bd);
QBM_CACHE_FLUSH_NO_DSR(bd, sizeof(qbm_gpd));
/* set gpd data len */
data_len = QBM_DES_GET_DATALEN(gpd);
QBM_DES_SET_DATALEN(gpd, data_len-offset);
/* set gpd checksum */
qbm_cal_set_checksum(gpd);
QBM_CACHE_FLUSH_NO_DSR(gpd, sizeof(qbm_gpd));
}else{
//4 <case 2> GPD->BUFF
/* set gpd data ptr */
data_ptr = (kal_uint8*)QBM_DES_GET_DATAPTR(gpd);
QBM_DES_SET_DATAPTR(gpd, data_ptr+offset);
/* set gpd data len */
data_len = QBM_DES_GET_DATALEN(gpd);
QBM_DES_SET_DATALEN(gpd, data_len-offset);
/* set bd checksum */
qbm_cal_set_checksum(gpd);
QBM_CACHE_FLUSH_NO_DSR(gpd, sizeof(qbm_gpd));
}
QBM_DSR();
}
/*!
* @function [INLINE] CCCIDEV_QBM_ENQ
* @brief Enqueue p_new_head/p_new_tail to pp_orig_head/pp_orig_tail
*
* @param p_new_head [IN] head of new gpd chain
* @param p_new_tail [IN] tail of new gpd chain
* @param pp_orig_head [IN/OUT] head of original gpd chain
* @param pp_orig_tail [IN/OUT] tail of original gpd chain
*
* @return void
*/
static __inline void CCCIDEV_QBM_ENQ(void *p_new_head, void *p_new_tail, void **pp_orig_head, void **pp_orig_tail)
{
kal_uint8 *p_ori_tail;
p_ori_tail = *pp_orig_tail;
if(*pp_orig_head == NULL){
*pp_orig_tail = p_new_tail;
*pp_orig_head = p_new_head;
}else{
/* link new queue */
QBM_DES_SET_NEXT(p_ori_tail, p_new_head);
// change tail to new tail
*pp_orig_tail = p_new_tail;
}
QBM_DES_SET_NEXT(*pp_orig_tail, NULL);
}
/*!
* @function [INLINE] CCCIDEV_QBM_DEQ
* @brief dequeue n GPD from pp_src_head/pp_src_tail to p_new_head/p_new_tail
* a accelerate version of qbmt_de_q_n
*
* @param pp_src_head [IN/OUT] head of src gpd chain
* @param pp_src_tail [IN/OUT] tail of src gpd chain
* @param n [IN] dequeue count
* @param pp_new_head [OUT] head of dest gpd chain
* @param pp_new_tail [OUT] tail of dest gpd chain
*
* @return void
*/
static __inline kal_uint32 CCCIDEV_QBM_DEQ(
void **pp_src_head,
void **pp_src_tail,
kal_uint32 n,
void **pp_new_head,
void **pp_new_tail
)
{
kal_uint32 deq_num = 0;
if(0 == n){
*pp_new_head = NULL;
*pp_new_tail = NULL;
return 0;
}
if(NULL == *pp_src_head){
EXT_ASSERT(NULL == *pp_src_tail, (kal_uint32)*pp_src_head, (kal_uint32) *pp_src_tail, 0);
*pp_new_head = NULL;
*pp_new_tail = NULL;
return 0;
}
*pp_new_head = *pp_src_head;
//for(deq_num = 0; deq_num < n; deq_num++){
do{
*pp_new_tail = *pp_src_head;
deq_num++;
*pp_src_head = QBM_DES_GET_NEXT(*pp_src_head);
}while((deq_num < n) && (NULL != *pp_src_head));
if(NULL == *pp_src_head){
*pp_src_tail = NULL;
}
return deq_num;
}
/*!
* @function [INLINE] CCCIDEV_FIX_IOR_NULL_LAST
* @brief if the last gpd of ior is == NULL, traverse the GPD chain to fill the last_gpd info
*
* @param ior [IN] input ior
*
* @return void
*/
static __inline void CCCIDEV_FIX_IOR_NULL_LAST(ccci_io_request_t* ior)
{
qbm_gpd *last_gpd = ior->last_gpd;
qbm_gpd *first_gpd = ior->first_gpd;
qbm_gpd *current_gpd;
/* fix the last_gpd == NULL case */
if (last_gpd == NULL)
{
current_gpd = first_gpd;
while ( current_gpd->p_next != NULL )
{
current_gpd = current_gpd->p_next;
}
ior->last_gpd = current_gpd;
}
}
/*!
* @function [INLINE] CCCIDEV_RM_CCCI_HEADERS
* @brief Tool function to remove the CCCI header in GPD->BD->BUFF / GPD->BUFF
*
* @param channel [IN] channel number for this CCCI header
* @param gpd [IN] pointer to the gpd
*
* @return KAL_TRUE: success, KAL_FALSE: channel number not matched
*/
static __inline kal_bool CCCIDEV_RM_CCCI_HEADERS(CCCI_CHANNEL_T channel, qbm_gpd *gpd)
{
CCCI_BUFF_T *pdata;
//4 <1> check gpd->bd->buff->channel = channel
pdata = CCCIDEV_GET_QBM_DATAPTR(gpd);
EXT_ASSERT(pdata, (kal_uint32)pdata, (kal_uint32)gpd, (kal_uint32)channel);
/* treat channel not match and size = 0 as invalid GPD*/
if(pdata->channel != channel || pdata->data[1] == sizeof(CCCI_BUFF_T)){
//hif_trace_error(CCCIDEV_TR_UL_CCCI_CH_ERR, pdata->channel, channel);
return KAL_FALSE;
}else{
//4 <2> move data pointer to raw data
CCCIDEV_PULL_QBM_DATAHEAD(gpd, sizeof(CCCI_BUFF_T));
}
return KAL_TRUE;
}
/*!
* @function [INLINE] ccci_dest_ior
* @brief Traverse ior chain to free the linked ior/GPD/BD/Buff
*
* @param ior [IN] pointer to the ior chain
*
* @return void
*/
static __inline void ccci_dest_ior(ccci_io_request_t *ior){
ccci_io_request_t *next_ior;
qbm_gpd* current_gpd;
EXT_ASSERT(ior, (kal_uint32)ior, 0, 0);
for (; ior; ior = next_ior) {
next_ior = ior->next_request;
EXT_ASSERT(ior->first_gpd, (kal_uint32)ior->first_gpd, (kal_uint32)ior, (kal_uint32)next_ior);
/* fix the last_gpd == NULL case */
if (ior->last_gpd == NULL)
{
current_gpd = ior->first_gpd;
while ( current_gpd->p_next != NULL )
{
current_gpd = current_gpd->p_next;
}
ior->last_gpd = current_gpd;
}
EXT_ASSERT(ior->first_gpd && ior->last_gpd, (kal_uint32)ior->first_gpd, (kal_uint32)ior->last_gpd, (kal_uint32)ior);
qbmt_dest_q(ior->first_gpd, ior->last_gpd);
}
}
/* Get address by a offset of the PD */
#define CCCIDEV_QBM_DES_GET_ADDR_BY_OFFSET(_p, _ofst) \
(void*)((kal_uint8*)(_p) + (_ofst))
/* Used for buffer and descriptor are in continus memory address */
#define CCCIDEV_QBM_DES_SET_DATA_BY_OFFSET(_p, _ofst) \
(QBM_GET_GPD_PTR(_p)->p_data_tbd = CCCIDEV_QBM_DES_GET_ADDR_BY_OFFSET(_p, _ofst))
#define CCCI_COMM_BD_OFST (64) /* p_data_tbd = 64 */
#define CCCI_COMM_GET_BD(_p) CCCIDEV_QBM_DES_GET_ADDR_BY_OFFSET(_p, CCCI_COMM_BD_OFST)
/* this code will set datalen and extlen to 0 */
/* Because in descriptor, they are in the 12 bytes */
#define CCCI_COMM_RESET_DATALEN_EXTLEN(_p) *(kal_uint32*)((kal_uint8*)(_p) + 12) = 0
/*!
* @function [INLINE] CCCIDEV_RST_CCCI_COMM_GPD_LIST
* @brief Reset the GPD list to the default value, type has to be QBM_TYPE_CCCI_COMM
*
* @param first_gpd [IN] pointer to the first GPD in the GPD chain
* @param last_gpd [IN] pointer to the last GPD in the GPD chain
*
* @return void
*/
static __inline kal_uint32 CCCIDEV_RST_CCCI_COMM_GPD_LIST(qbm_gpd* first_gpd, qbm_gpd* last_gpd)
{
qbm_gpd* current_gpd = NULL;
qbm_gpd* next_gpd = NULL;
kal_uint32 num_gpd = 0;
EXT_ASSERT(first_gpd && last_gpd, (kal_uint32)first_gpd, (kal_uint32)last_gpd, 0);
current_gpd = first_gpd;
do {
next_gpd = QBM_DES_GET_NEXT(current_gpd);
qbm_reset_pd(QBM_TYPE_CCCI_COMM, (void*)current_gpd);
qbm_cal_set_checksum((kal_uint8 *)current_gpd);
QBM_CACHE_FLUSH_NO_DSR(current_gpd, sizeof(qbm_gpd));
num_gpd ++;
if ( current_gpd == last_gpd )
{
break;
}
current_gpd = next_gpd;
} while ( current_gpd != NULL );
QBM_DSR();
return num_gpd;
}
/*!
* @function [Prototype] cccidev_dl_header_handle_cb
* @brief Prototype of function to handle each packet's CCCI Header
*
* @param pDevice [IN] pointer to the CCCIDEV device
* @param p_ccci_head [IN] pointer to ccci header buffer
* @param kal_uint8 [IN] pointer to the data buffer
*
* @return 0, unused
*/
typedef kal_uint32 (*cccidev_dl_header_handle_cb)(void* p_device, CCCI_BUFF_T* p_ccci_head, kal_uint8* pdata, kal_uint32 data_len);
/*!
* @function [static] CCCIDEV_SPD_PI_RELAYOUT
* @brief Traverse the input GPD list and insert the CCCI header on the first BD->data
*
* @param spd [IN] pointer to the SPD in the GPD chain
*
* @return relayout success
*/
static __inline kal_uint32 CCCIDEV_SPD_PI_RELAYOUT(qbm_gpd* p_spd){
hif_spd_ext_header *p_spd_ext = (hif_spd_ext_header*)QBM_SPD_GET_EXT((qbm_spd*)p_spd);
hif_spd_packet_header *p_spd_ph;
qbm_spd_pie *p_spd_pie;
qbm_spd_pi *p_spd_pi = QBM_SPD_GET_PI((qbm_spd*)p_spd);
kal_uint16 i, pkt_num = 0, header_len = sizeof(CCCI_BUFF_T);
EXT_ASSERT(QBM_DES_GET_PDT(p_spd) == DES_FLAG_BIT_SPD3,QBM_DES_GET_PDT(p_spd), (kal_uint32)p_spd, 0);
p_spd_pie = QBM_SPD_PI_GET_FIRST_PIE(p_spd_pi);
p_spd_ph = HIF_SPD_EXT_GET_FIRST_PH(p_spd_ext);
pkt_num = QBM_SPD_PI_GET_PKTNUM(p_spd_pi);
HIF_SPD_EXT_SET_PKTNUM(p_spd_ext, pkt_num);
HIF_SPD_EXT_SET_SPD1_HEADERLEN(p_spd_ext , (kal_uint8)header_len);
#ifdef CCCIDEV_SPD_RELAYOUT_SET_PKTNUM_TRACE
if(KAL_TRUE != kal_query_systemInit() && KAL_FALSE == INT_QueryExceptionStatus())
CCCIDEV_SPD_RELAYOUT_SET_PKTNUM_TRACE(pkt_num, (kal_uint32) p_spd_pi, (kal_uint32) p_spd_ext);
#endif
QBM_DES_SET_SPD1(p_spd);
for(i = 1; i <=pkt_num; i++){
kal_mem_cpy(p_spd_ph, p_spd_pie, sizeof(qbm_spd_pie));
// @This is the last packet : check if EPDCP set the EOL correctly, if this assert happend, please contact EPDCP owner
if (i == pkt_num){
EXT_ASSERT(HIF_SPD_PH_GET_EOL(p_spd_ph), \
(kal_uint32)p_spd, pkt_num, (kal_uint32)p_spd_ph);
}
// @This is an EOL packet : if get EOL but not last packet, should break, no need to handle remaining packet
else if (HIF_SPD_PH_GET_EOL(p_spd_ph)){
#ifdef CCCIDEV_SPD_RELAYOUT_GET_EOL_BREAK_TRACE
if(KAL_TRUE != kal_query_systemInit() && KAL_FALSE == INT_QueryExceptionStatus())
CCCIDEV_SPD_RELAYOUT_GET_EOL_BREAK_TRACE(pkt_num, i, (kal_uint32) p_spd_ph);
#endif
break;
}
// @This is a normal packet : if get not last GPD, move to next ph
else{
p_spd_ph = HIF_SPD_PH_NEXT(p_spd_ph, (kal_uint8)header_len);
p_spd_pie = QBM_SPD_PIE_NEXT(p_spd_pie);
}
}
return 0;
}
/*!
* @function [static] CCCIDEV_PROCESS_DL_GPD_LIST
* @brief Traverse the input GPD list and insert the CCCI header on the first BD->data
*
* @param pDevice [IN] pointer to the CCCIDEV device
* @param first_gpd [IN] pointer to the first GPD in the GPD chain
* @param last_gpd [IN] pointer to the last GPD in the GPD chain
* @param cccidev_dl_header_handle_cb [IN] pointer of the callback function to handle each packet's CCCI Header
*
* @return number of gpd/spd in between first_gpd and last_gpd
*/
static __inline kal_uint32 CCCIDEV_PROCESS_DL_GPD_LIST(void* pDevice, qbm_gpd* first_gpd, qbm_gpd* last_gpd, cccidev_dl_header_handle_cb cb)
{ /*process_tx_gpd_list*/
qbm_gpd* p_gpd = NULL;
kal_uint32 gpd_cnt = 0;
CCCI_BUFF_T *p_ccci_head;
kal_uint8 current_pdt;
hif_spd_packet_header *p_spd_ph, *p_spd_ph_next=NULL; //spd packet head
kal_uint8 *p_payload, *p_payload_next=NULL; //spd packet payload
hif_spd_ext_header *p_spd_ext; //spd extention
kal_uint16 pkt_num;
kal_uint32 i, payload_len, header_len=0;
kal_uint32 data_len = 0;
EXT_ASSERT(first_gpd && last_gpd, (kal_uint32)first_gpd, (kal_uint32)last_gpd, (kal_uint32)pDevice);
p_gpd = first_gpd;
do {
current_pdt = QBM_DES_GET_PDT(p_gpd);
if(current_pdt == DES_FLAG_BIT_SPD3){
CCCIDEV_SPD_PI_RELAYOUT(p_gpd);
current_pdt = QBM_DES_GET_PDT(p_gpd);
}
EXT_ASSERT((( current_pdt == DES_FLAG_BIT_SPD1) || (current_pdt == DES_FLAG_BIT_GPD)), \
(kal_uint32)current_pdt, (kal_uint32)pDevice, (kal_uint32)p_gpd);
if(current_pdt == DES_FLAG_BIT_SPD1){
//4 <1> SPD1 handling
p_spd_ext = (hif_spd_ext_header*)QBM_SPD_GET_EXT((qbm_spd*)p_gpd);
p_spd_ph = HIF_SPD_EXT_GET_FIRST_PH((hif_spd_ext_header*)p_spd_ext);
p_payload = QBM_DES_GET_DATAPTR((qbm_spd*)p_gpd);
pkt_num = HIF_SPD_EXT_GET_PKTNUM((hif_spd_ext_header*)p_spd_ext);
//[tk6291_mw_hif_spd_design_doc_v1.0: The packet number should be larger than 1
EXT_ASSERT(pkt_num >= 1, pkt_num, (kal_uint32)p_spd_ext, (kal_uint32)(qbm_spd*)p_gpd);
//4 <1.1> set spd1_header_len = sizeof(CCCI_BUFF_T);
//Header length fill by first user
header_len = HIF_SPD_EXT_GET_SPD1_HEADERLEN((hif_spd_ext_header*)p_spd_ext);
p_spd_ph_next = HIF_SPD_PH_NEXT(p_spd_ph, header_len); // initial
#ifdef CCCIDEV_PROCESS_DL_SPD_TRACE
if(KAL_TRUE != kal_query_systemInit() && KAL_FALSE == INT_QueryExceptionStatus())
CCCIDEV_PROCESS_DL_SPD_TRACE(pkt_num, (kal_uint32)p_gpd);
#endif
//4 <1.2> Set IGR for 1st pkt, for MBIM use only, and move to 2nd PH
//iterate from the 1st ph
for (i=1; i<=pkt_num; i++){
payload_len = HIF_SPD_PH_GET_PAYLOAD_LEN(p_spd_ph);
if (i != pkt_num){
p_spd_ph_next = HIF_SPD_PH_NEXT(p_spd_ph, header_len);
p_payload_next = QBM_SPD_PAYLOAD_NEXT(p_payload, payload_len);
}
if(0 == HIF_SPD_PH_GET_IGR(p_spd_ph)){ // if IGR bit is not set
//4 <1.3> append CCCI header CCCI_BUFF_T
p_ccci_head = (CCCI_BUFF_T *)HIF_SPD_PH_GET_HEADER(p_spd_ph);
// call CCCI Device CCCI header handle
cb(pDevice, p_ccci_head, p_payload, payload_len);
// payload length check, if this assert happend, please contact EPDCP owner
EXT_ASSERT(payload_len, \
(kal_uint32)p_gpd, pkt_num, (kal_uint32)p_spd_ph);
}
else{ // if IGR bit is set
#ifdef CCCIDEV_PROCESS_DL_SPD_SET_IGR_TRACE
if(KAL_TRUE != kal_query_systemInit() && KAL_FALSE == INT_QueryExceptionStatus())
CCCIDEV_PROCESS_DL_SPD_SET_IGR_TRACE(HIF_SPD_PH_GET_IGR(p_spd_ph), i, (kal_uint32)p_spd_ph);
#endif
}
// @This is the last packet : check if EPDCP set the EOL correctly, if this assert happend, please contact EPDCP owner
if (i == pkt_num)
{
EXT_ASSERT(HIF_SPD_PH_GET_EOL(p_spd_ph), \
(kal_uint32)p_gpd, pkt_num, (kal_uint32)p_spd_ph);
QBM_CACHE_FLUSH(p_spd_ext, sizeof(qbm_spd_ext));
}
// @This is an EOL packet :if get EOL but not last packet, should breakm, no need to handle remaining packet
else if (HIF_SPD_PH_GET_EOL(p_spd_ph)){
#ifdef CCCIDEV_SPD_RELAYOUT_GET_EOL_BREAK_TRACE
if(KAL_TRUE != kal_query_systemInit() && KAL_FALSE == INT_QueryExceptionStatus())
CCCIDEV_SPD_RELAYOUT_GET_EOL_BREAK_TRACE(pkt_num, i, (kal_uint32) p_spd_ph);
#endif
QBM_CACHE_FLUSH(p_spd_ext, sizeof(qbm_spd_ext));
break;
}
// @This is a normal packet : if get not last GPD, move to next ph
else
{
p_spd_ph = p_spd_ph_next;
p_payload = p_payload_next;
}
}
}else
{
//4 <2> GPD handling
/* ASSERT if not GPD type, if this assert happens meaning DL is neither SPD type1 nor GPD
please seek for EPDCP owner's help*/
EXT_ASSERT((current_pdt == DES_FLAG_BIT_GPD), \
(kal_uint32)current_pdt, (kal_uint32)pDevice, (kal_uint32)p_gpd);
//4 <2.1> append CCCI header CCCI_BUFF_T
// CCCIDEV append ccci header in BD EXT(only for CCMNI with first empty BD) or GPD EXT
if((0 != QBM_DES_GET_BDP(p_gpd)) && (0 == QBM_DES_GET_DATALEN (QBM_DES_GET_DATAPTR(p_gpd)))){
//4 <case 1> GPD->BD->BUFF
/* Store the DL CCCI header in the BD extention part */
void* bd = QBM_DES_GET_DATAPTR(p_gpd);
QBM_DES_SET_EXTLEN(bd, sizeof(CCCI_BUFF_T));
p_ccci_head = (CCCI_BUFF_T *)QBM_DES_GET_EXT(bd);
qbm_cal_set_checksum(bd);
QBM_CACHE_FLUSH(bd, sizeof(qbm_gpd));
QBM_DES_SET_DATALEN(p_gpd, CCCIDEV_GET_QBM_DATALEN(p_gpd)+sizeof(CCCI_BUFF_T));
data_len = CCCIDEV_GET_QBM_DATALEN(p_gpd);
}
else{
//4 <case 2> GPD->BUFF
/* Store the DL CCCI header in the GPD extention part */
QBM_DES_SET_EXTLEN(p_gpd, sizeof(CCCI_BUFF_T));
p_ccci_head = (CCCI_BUFF_T *)QBM_DES_GET_EXT(p_gpd);
data_len = CCCIDEV_GET_QBM_DATALEN(p_gpd) + sizeof(CCCI_BUFF_T);
}
p_payload = CCCIDEV_GET_QBM_DATAPTR(p_gpd);
// call CCCI Device CCCI header handle
cb(pDevice, p_ccci_head, p_payload, data_len);
}
gpd_cnt++;
if ( p_gpd == last_gpd )
{
break;
}
//make sure there is no invalid GPD in the list
EXT_ASSERT(QBM_DES_GET_NEXT(p_gpd) != NULL, (kal_uint32)p_gpd, (kal_uint32)first_gpd, (kal_uint32)last_gpd);
p_gpd = QBM_DES_GET_NEXT(p_gpd);
} while ( p_gpd != NULL );
return gpd_cnt;
}
/*!
* @function [Prototype] cccidev_dl_header_handle_cb
* @brief Prototype of function to handle each packet's CCCI Header
*
* @param pDevice [IN] pointer to the CCCIDEV device
* @param p_ccci_head [IN] pointer to ccci header buffer
* @param kal_uint8 [IN] pointer to the data buffer
*
* @return 0, unused
*/
typedef kal_uint32 (*cccidev_dl_header_handle_only_first_cb)(void* p_device, CCCI_BUFF_T* p_ccci_head, kal_uint8* pdata, kal_uint32 data_len, kal_uint16 rem_gpd);
/*!
* @function [static] CCCIDEV_PROCESS_DL_GPD_LIST
* @brief Traverse the input GPD list and insert the CCCI header on the first BD->data
*
* @param pDevice [IN] pointer to the CCCIDEV device
* @param first_gpd [IN] pointer to the first GPD in the GPD chain
* @param last_gpd [IN] pointer to the last GPD in the GPD chain
* @param cccidev_dl_header_handle_cb [IN] pointer of the callback function to handle each packet's CCCI Header
*
* @return number of gpd/spd in between first_gpd and last_gpd
*/
static __inline kal_uint32 CCCIDEV_PROCESS_DL_GPD_LIST_ONLY_FIRST(void* pDevice, qbm_gpd* first_gpd, qbm_gpd* last_gpd, cccidev_dl_header_handle_only_first_cb cb, kal_uint16 rem_gpd)
{ /*process_tx_gpd_list*/
qbm_gpd* p_gpd = NULL;
kal_uint32 gpd_cnt = 0;
CCCI_BUFF_T *p_ccci_head;
kal_uint8 current_pdt;
hif_spd_packet_header *p_spd_ph, *p_spd_ph_next=NULL; //spd packet head
kal_uint8 *p_payload, *p_payload_next=NULL; //spd packet payload
hif_spd_ext_header *p_spd_ext; //spd extention
kal_uint16 pkt_num;
kal_uint32 i, payload_len, header_len =0;
kal_bool is_first_SPD = KAL_TRUE;
EXT_ASSERT(first_gpd && last_gpd, (kal_uint32)first_gpd, (kal_uint32)last_gpd, (kal_uint32)pDevice);
p_gpd = first_gpd;
do {
current_pdt = QBM_DES_GET_PDT(p_gpd);
if(current_pdt == DES_FLAG_BIT_SPD3){
CCCIDEV_SPD_PI_RELAYOUT(p_gpd);
current_pdt = QBM_DES_GET_PDT(p_gpd);
}
EXT_ASSERT((( current_pdt == DES_FLAG_BIT_SPD1) || (current_pdt == DES_FLAG_BIT_GPD)), \
(kal_uint32)current_pdt, (kal_uint32)pDevice, (kal_uint32)p_gpd);
if(current_pdt == DES_FLAG_BIT_SPD1)
{
p_spd_ext = (hif_spd_ext_header*)QBM_SPD_GET_EXT((qbm_spd*)p_gpd);
p_spd_ph = HIF_SPD_EXT_GET_FIRST_PH((hif_spd_ext_header*)p_spd_ext);
p_spd_ph_next = HIF_SPD_PH_NEXT(p_spd_ph, 0); //initial
p_payload = QBM_DES_GET_DATAPTR((qbm_spd*)p_gpd);
pkt_num = HIF_SPD_EXT_GET_PKTNUM((hif_spd_ext_header*)p_spd_ext);
//[tk6291_mw_hif_spd_design_doc_v1.0: The packet number should be larger than 1
EXT_ASSERT(pkt_num >= 1, pkt_num, (kal_uint32)p_spd_ext, (kal_uint32)(qbm_spd*)p_gpd);
//4 <1.1> set spd1_header_len = sizeof(CCCI_BUFF_T);
//Header length fill by first user
header_len = HIF_SPD_EXT_GET_SPD1_HEADERLEN((hif_spd_ext_header*)p_spd_ext);
#ifdef CCCIDEV_PROCESS_DL_SPD_TRACE
if(KAL_TRUE != kal_query_systemInit() && KAL_FALSE == INT_QueryExceptionStatus())
CCCIDEV_PROCESS_DL_SPD_TRACE(pkt_num, (kal_uint32)p_gpd);
#endif
//4 <1.2> Set IGR for 1st pkt, for MBIM use only, and move to 2nd PH
//iterate from the 1st ph
if(is_first_SPD == KAL_TRUE){ // only add CCCI header to first SPD
is_first_SPD = KAL_FALSE;
for (i=1; i<=pkt_num; i++){
payload_len = HIF_SPD_PH_GET_PAYLOAD_LEN(p_spd_ph);
if (i != pkt_num){
p_spd_ph_next = HIF_SPD_PH_NEXT(p_spd_ph, header_len);
p_payload_next = QBM_SPD_PAYLOAD_NEXT(p_payload, payload_len);
}
if(0 == HIF_SPD_PH_GET_IGR(p_spd_ph)){ // if IGR bit is not set
//4 <1.3> append CCCI header CCCI_BUFF_T
p_ccci_head = (CCCI_BUFF_T *)HIF_SPD_PH_GET_HEADER(p_spd_ph);
// call CCCI Device CCCI header handle
cb(pDevice, p_ccci_head, p_payload, payload_len, rem_gpd);
// This is SPD mode
if(rem_gpd > 0)
p_ccci_head->data[1] = p_ccci_head->data[1] | (1 << 31);
// payload length check, if this assert happend, please contact EPDCP owner
EXT_ASSERT(payload_len, \
(kal_uint32)p_gpd, pkt_num, (kal_uint32)p_spd_ph);
break;//only handle first header
}
else{ // if IGR bit is set
#ifdef CCCIDEV_PROCESS_DL_SPD_SET_IGR_TRACE
if(KAL_TRUE != kal_query_systemInit() && KAL_FALSE == INT_QueryExceptionStatus())
CCCIDEV_PROCESS_DL_SPD_SET_IGR_TRACE(HIF_SPD_PH_GET_IGR(p_spd_ph), i, (kal_uint32)p_spd_ph);
#endif
}
// @This is a normal packet : if get not last GPD, move to next ph
//else
{
p_spd_ph = p_spd_ph_next;
p_payload = p_payload_next;
}
}
}
// Flush all spd ext
QBM_CACHE_FLUSH(p_spd_ext, sizeof(qbm_spd_ext));
}
else
{
//4 <2> GPD handling
/* ASSERT if not GPD type, if this assert happens meaning DL is neither SPD type1 nor GPD
please seek for EPDCP owner's help*/
EXT_ASSERT((current_pdt == DES_FLAG_BIT_GPD), \
(kal_uint32)current_pdt, (kal_uint32)pDevice, (kal_uint32)p_gpd);
//4 <2.1> append CCCI header CCCI_BUFF_T
// CCCIDEV append ccci header in BD EXT(only for CCMNI with first empty BD) or GPD EXT
if((0 != QBM_DES_GET_BDP(p_gpd)) && (0 == QBM_DES_GET_DATALEN (QBM_DES_GET_DATAPTR(p_gpd)))){
//4 <case 1> GPD->BD->BUFF
/* Store the DL CCCI header in the BD extention part */
void* bd = QBM_DES_GET_DATAPTR(p_gpd);
QBM_DES_SET_EXTLEN(bd, sizeof(CCCI_BUFF_T));
p_ccci_head = (CCCI_BUFF_T *)QBM_DES_GET_EXT(bd);
qbm_cal_set_checksum(bd);
QBM_CACHE_FLUSH(bd, sizeof(qbm_gpd));
QBM_DES_SET_DATALEN(p_gpd, CCCIDEV_GET_QBM_DATALEN(p_gpd)+sizeof(CCCI_BUFF_T));
CCCI_STREAM_SET_LEN(p_ccci_head, CCCIDEV_GET_QBM_DATALEN(p_gpd));
/* hifsdioq_set_gpd will set HWO and set checksum */
//qbm_cal_set_checksum(p_gpd);
//QBM_CACHE_FLUSH(p_gpd, sizeof(qbm_gpd));
}
else{
//4 <case 2> GPD->BUFF
/* Store the DL CCCI header in the GPD extention part */
QBM_DES_SET_EXTLEN(p_gpd, sizeof(CCCI_BUFF_T));
p_ccci_head = (CCCI_BUFF_T *)QBM_DES_GET_EXT(p_gpd);
CCCI_STREAM_SET_LEN(p_ccci_head, CCCIDEV_GET_QBM_DATALEN(p_gpd)+sizeof(CCCI_BUFF_T));
}
p_payload = CCCIDEV_GET_QBM_DATAPTR(p_gpd);
// call CCCI Device CCCI header handle
cb(pDevice, p_ccci_head, p_payload, CCCIDEV_GET_QBM_DATALEN(p_gpd), rem_gpd);
break; // GPD mode only processes first gpd
}
gpd_cnt++;
if ( p_gpd == last_gpd )
{
break;
}
//make sure there is no invalid GPD in the list
EXT_ASSERT(QBM_DES_GET_NEXT(p_gpd) != NULL, (kal_uint32)p_gpd, (kal_uint32)first_gpd, (kal_uint32)last_gpd);
p_gpd = QBM_DES_GET_NEXT(p_gpd);
} while ( p_gpd != NULL );
return gpd_cnt;
}
#endif //#ifndef _CCCIDEV_QBM_H