blob: 604ab336fa4fa5624ea36b91f8063aab24892efb [file] [log] [blame]
yu.dongc33b3072024-08-21 23:14:49 -07001/*****************************************************************************
2* Copyright Statement:
3* --------------------
4* This software is protected by Copyright and the information contained
5* herein is confidential. The software may not be copied and the information
6* contained herein may not be used or disclosed except with the written
7* permission of MediaTek Inc. (C) 2012
8*
9* BY OPENING THIS FILE, BUYER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
10* THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE")
11* RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO BUYER ON
12* AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL WARRANTIES,
13* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF
14* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NONINFRINGEMENT.
15* NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH RESPECT TO THE
16* SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY, INCORPORATED IN, OR
17* SUPPLIED WITH THE MEDIATEK SOFTWARE, AND BUYER AGREES TO LOOK ONLY TO SUCH
18* THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO. MEDIATEK SHALL ALSO
19* NOT BE RESPONSIBLE FOR ANY MEDIATEK SOFTWARE RELEASES MADE TO BUYER'S
20* SPECIFICATION OR TO CONFORM TO A PARTICULAR STANDARD OR OPEN FORUM.
21*
22* BUYER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S ENTIRE AND CUMULATIVE
23* LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE RELEASED HEREUNDER WILL BE,
24* AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE MEDIATEK SOFTWARE AT ISSUE,
25* OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE CHARGE PAID BY BUYER TO
26* MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE.
27*
28* THE TRANSACTION CONTEMPLATED HEREUNDER SHALL BE CONSTRUED IN ACCORDANCE
29* WITH THE LAWS OF THE STATE OF CALIFORNIA, USA, EXCLUDING ITS CONFLICT OF
30* LAWS PRINCIPLES. ANY DISPUTES, CONTROVERSIES OR CLAIMS ARISING THEREOF AND
31* RELATED THERETO SHALL BE SETTLED BY ARBITRATION IN SAN FRANCISCO, CA, UNDER
32* THE RULES OF THE INTERNATIONAL CHAMBER OF COMMERCE (ICC).
33*
34*****************************************************************************/
35
36/*******************************************************************************
37 * Filename:
38 * ---------
39 * cccidev_qbm.h
40 *
41 * Project:
42 * --------
43 * MOLY
44 *
45 * Description:
46 * ------------
47 * Defines the common qmu_bm macros or inline functions for CCCI devices
48 *
49 * Author:
50 * -------
51 * -------
52 *
53 * ==========================================================================
54 * $Log$
55 *
56 * 09 18 2020 li-cheng.tsai
57 * [MOLY00569647] [MP7.PRECHECKIN.DEV][Code sync] sync code from T700
58 * [R3.MP][OA][CCCI]code sync from T700
59 *
60 * 09 15 2020 li-cheng.tsai
61 * [MOLY00569647] [MP7.PRECHECKIN.DEV][Code sync] sync code from T700
62 * [MP7.PRECHECKIN.DEV][OA][CCCI]code sync from T700
63 *
64 * 08 04 2020 actory.ou
65 * [MOLY00554534] [Colgin][Code sync] sync code from MT6880.MP
66 * [T700][OA][CCCI] sync from MT6880
67 *
68 * 07 07 2020 actory.ou
69 * [MOLY00543186] [Colgin] code sync to NR15.R3.MT6880.MP
70 * [R3.MT6880.MP][OA][CCCI] sync from COLGIN.SB.SMT.DEV
71 *
72 * 05 19 2020 actory.ou
73 * [MOLY00525599] code sync for Colgin
74 * [NR15.R3.COLGIN.SB.SMT.DEV][OA][CCCI] code sync from 19NOV
75 *
76 * 12 18 2019 actory.ou
77 * [MOLY00465742] [Gen97] add L5 channels and change CCIF SHM layout
78 * [19NOV.DEV][OA] add L5 channels
79 *
80 * 09 15 2017 chien-hui.lu
81 * [MOLY00278317] [CCCI][LHIFCORE][CCISMCORE] Performance improvement of INT_QueryExceptionStatus
82 * [CCCI][LHIFCORE][CCISMCORE] Performance improvement of INT_QueryExceptionStatus.
83 *
84 * 08 01 2017 chien-hui.lu
85 * [MOLY00260287] MD CCCI add cache API enhance to LR12 trunk
86 * [CCCI] cache API enhancement and aggregation, porting from UMOLY.
87 *
88 * 11 08 2016 cs.huang
89 * [MOLY00204430] [CCCI] MT6293 change
90 * [CCCI] Fast CCCI header problem
91 *
92 * 08 15 2016 cs.huang
93 * [MOLY00197453] [CCCI] Fast CCCI header change SPD header size
94 * [CCCI] Fast CCCI header problem
95 *
96 * 06 07 2016 cs.huang
97 * [MOLY00183140] [Coverity Scanned Code Defect]CID:138824 code defect happened in /mcu/common/interface/service/hif/cccidev_qbm.h
98 * [CCCI] Fix coverity warning
99 * 06 01 2016 cs.huang
100 * [MOLY00182647] [CCCI] Fast CCCI header
101 * [CCCI] Fast CCCI header
102 *
103 * 06 01 2016 cs.huang
104 * [MOLY00182647] [CCCI] Fast CCCI header
105 * [CCCI] Fast CCCI header
106 *
107 * 12 28 2015 cs.huang
108 * [MOLY00155074] [CCCI] Fix CCCI header length for TTY and fix IT program
109 * [CCCI] Fix CCCI header length for TTY and fix IT program
110 *
111 * 12 28 2015 cs.huang
112 * [MOLY00155074] [CCCI] Fix CCCI header length for TTY and fix IT program
113 * [CCCI] Fix CCCI header length for TTY and fix IT program
114 * 08 07 2015 cs.huang
115 * [MOLY00136043] cccidev_qbm.h assertion
116 * [CCMNI] Fix SPD EOL problem
117 *
118 *
119 * 08 07 2015 cs.huang
120 * [MOLY00136043] cccidev_qbm.h assertion
121 * [CCMNI] Fix SPD EOL problem
122 *
123 * 08 06 2015 cs.huang
124 * [MOLY00135464] [CCCI] New CCCI handshake flow
125 * [CCCI] New CCCI handshake flow
126 *
127 * 08 06 2015 cs.huang
128 * [MOLY00135464] [CCCI] New CCCI handshake flow
129 * [CCCI] New CCCI handshake flow
130 * 07 28 2015 cs.huang
131 * [MOLY00131268] [CCMNI] Add SPD trace
132 * [CCMNI] Add SPD trace
133 *
134 * 07 28 2015 cs.huang
135 * [MOLY00131268] [CCMNI] Add SPD trace
136 * [CCMNI] Add SPD trace
137 *
138 * 07 24 2015 cs.huang
139 * [MOLY00131268] [CCMNI] Add SPD trace
140 * [CCMNI] Add SPD trace timing
141 *
142 * 07 23 2015 cs.huang
143 * [MOLY00131268] [CCMNI] Add SPD trace
144 * [CCMNI] Add SPD trace
145 *
146 * 05 08 2015 cs.huang
147 * [MOLY00112001] [CCCI] Change CCCI sequence definition in CCCI header.
148 * [CCCI] Change CCCI sequence definition in CCCI header.
149 *
150 * 05 05 2015 cs.huang
151 * [MOLY00111097] [CCCI] Modify RMPU buffer definition
152 * [CCCI] Modify polling buffer defination for RMPU
153 *
154 * 04 15 2015 i-wei.tsai
155 * [MOLY00107626] [TK6291][CCCITTY] enable sequence check and exception SPD support
156 * .
157 *
158 * 03 27 2015 ap.wang
159 * [MOLY00100246] [UMOLY] Fix SPD type3 re-layout error
160 * Add CCCI Len for SPD DL v2
161 *
162 * 03 24 2015 ap.wang
163 * [MOLY00100246] [UMOLY] Fix SPD type3 re-layout error
164 * .
165 *
166 * 01 23 2015 ap.wang
167 * [MOLY00092900] [UMOLY] L2 Copro zero len packet on SPD
168 * .
169 *
170 * 12 10 2014 cs.huang
171 * [MOLY00080351] [MT6291][CCCI] Add L1Core CCCI service (CCCI SYSMSG/RPC/IPC)
172 * [CCCI] PCore/L1Core CCCI enhancement
173 *
174 * 11 13 2014 cs.huang
175 * [MOLY00084049] [CCCI] Merging P2P CCCI related change
176 * Merging
177 *
178 * //UMOLY/DEV/MT6291_DEV/mcu/pcore/...
179 *
180 * to //UMOLY/TRUNK/UMOLY/mcu/pcore/...
181 *
182 * 11 13 2014 cs.huang
183 * [MOLY00081425] [TK6291_DEV] Add SPD sw solution
184 * Merging
185 *
186 * //UMOLY/DEV/MT6291_DEV/mcu/pcore/...
187 *
188 * to //UMOLY/TRUNK/UMOLY/mcu/pcore/...
189 *
190 * 11 13 2014 cs.huang
191 * [MOLY00075481] Add CCCI SPD DL support
192 * Merging
193 *
194 * //UMOLY/DEV/MT6291_DEV/mcu/pcore/...
195 *
196 * to //UMOLY/TRUNK/UMOLY/mcu/pcore/...
197 *
198 *
199 *
200 * 08 14 2014 ap.wang
201 * [MOLY00075481] Add CCCI SPD DL support
202 * CCCIDEV SPD DL common process
203 * 07 22 2014 cs.huang
204 * [MOLY00071952] [CCCI] Add new CCCI debug mechanism (1. CCCI seq check 2. AP polling MD status)
205 * [CCCI] ccci new debug mechanism
206 *
207 * 07 22 2014 cs.huang
208 * [MOLY00071952] [CCCI] Add new CCCI debug mechanism (1. CCCI seq check 2. AP polling MD status)
209 * [CCCI] CCCI new debug mechanism
210 * 07 09 2014 cs.huang
211 * [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
212 * [CCCI RPC] Fix ccci rpc coding defect in ccci_rpc_receive_cb
213 *
214 * 07 09 2014 cs.huang
215 * [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
216 * [CCCI RPC] Fix ccci rpc coding defect in ccci_rpc_receive_cb
217 *
218 * 09 06 2013 ap.wang
219 * [MOLY00036761] [CCCI] Add L2 trace log [CCCI] Add L2 trace log
220 *
221 * 06 25 2013 ian.cheng
222 * [MOLY00027392] [CCCI]CCCIDEV_GET_QBM_DATALEN should return GPD.len for DHL
223 * [MOLY][CCCI] CCCIDEV_GET_QBM_DATALEN return GPD length even when there's BD
224 *
225 * 03 14 2013 ap.wang
226 * [MOLY00011922] [CCCIDEV] Add GPD cache flush after set checksum
227 * [CCCIDEV] Add GPD cache flush after set checksum
228 *
229 * 02 21 2013 i-wei.tsai
230 * [MOLY00010624] CCCITTY integartion test code revise
231 * remove internal _reset_ccci_common
232 *
233 * 02 04 2013 i-wei.tsai
234 * [MOLY00009892] Rename as MT6290
235 * Rename project name as MT6290
236 *
237 * 01 08 2013 i-wei.tsai
238 * [MOLY00008347] [MT6290] [CCCI] CCCI re-Architecture
239 * sync latest version of new features
240 *
241 * 12 06 2012 ian.cheng
242 * [MOLY00007169] [CCCI_SDIO] MOLY phase in
243 * [MOLY][CCCI_SDIO] 1st version of MT6290 CCCI feature
244 *
245 * 12 06 2012 ian.cheng
246 * [MOLY00007169] [CCCI_SDIO] MOLY phase in
247 * [MOLY][CCCI_SDIO] 1st version of MT6290 CCCI feature
248 ****************************************************************************/
249#ifndef _CCCIDEV_QBM_H
250#define _CCCIDEV_QBM_H
251#include "kal_public_api.h"
252#include "qmu_bm.h"
253#include "qmu_bm_util.h"
254#include "ccci_if.h" /* ccci_io_request_t */
255#include "hif_spd_ext.h"
256
257#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
258
259/*!
260 * @function [INLINE] CCCICOMM_SET_QBM_DATALEN
261 * @brief Set data length for QBM_TYPE_CCCI_COMM by QBM_DES_SET_DATALEN
262 *
263 * @param gpd [IN] pointer to the GPD
264 *
265 * @return void
266 */
267static __inline void CCCICOMM_SET_QBM_DATALEN(void* gpd, kal_uint32 data_len)
268{
269 void* bd = NULL;
270
271 EXT_ASSERT(NULL != gpd, (kal_uint32)gpd, data_len, 0);
272 /*QBM_TYPE_CCCI_COMM specific function*/
273 EXT_ASSERT(QBM_TYPE_CCCI_COMM == QBM_GET_TYPE(gpd), (kal_uint32)QBM_GET_TYPE(gpd), (kal_uint32)gpd, data_len);
274 /*Must have BD*/
275 EXT_ASSERT(0 != QBM_DES_GET_BDP(gpd), (kal_uint32)QBM_DES_GET_BDP(gpd), (kal_uint32)gpd, data_len);
276
277 bd = QBM_DES_GET_DATAPTR(gpd);
278 EXT_ASSERT(NULL!=bd, (kal_uint32)gpd, (kal_uint32)bd, data_len);
279 QBM_DES_SET_DATALEN(bd, data_len);
280 qbm_cal_set_checksum((kal_uint8 *)bd);
281
282 QBM_DES_SET_DATALEN(gpd, data_len);
283 qbm_cal_set_checksum((kal_uint8 *)gpd);
284}
285
286/*!
287 * @function [INLINE] CCCIDEV_GET_QBM_DATALEN
288 * @brief Obtain the data length of first BD in GPD list.
289 * Possible application is used during inserting layer headers ex. CCCI headers.
290 *
291 * @param gpd [IN] pointer to the GPD
292 *
293 * @return Return gpd->1st_bd->data_len / gpd->data_len
294 */
295static __inline kal_uint32 CCCIDEV_GET_QBM_DATALEN(void* gpd)
296{
297 kal_uint32 data_len = 0;
298
299 EXT_ASSERT(NULL!=gpd, (kal_uint32) gpd,0 ,0);
300 /* user should put length in gpd.len
301 gpd.len = bd.ext_len + bd.len */
302 data_len = QBM_DES_GET_DATALEN(gpd);
303 return data_len;
304}
305
306#include <ex_public.h>
307/*!
308 * @function [INLINE] CCCIDEV_GET_QBM_DATAPTR
309 * @brief Obtain the pointer of data.
310 *
311 * @param gpd [IN] pointer to the GPD
312 *
313 * @return Return gpd->1st_bd->p_data_tbd / gpd->p_data_tbd
314 */
315
316static __inline void* CCCIDEV_GET_QBM_DATAPTR(void* gpd)
317{
318 void* bd = NULL;
319 void* data_ptr = NULL;
320
321 EXT_ASSERT(NULL!=gpd, (kal_uint32) gpd, 0, 0);
322 if(0 != QBM_DES_GET_BDP(gpd)){
323 //4 <case 1> GPD->BD->BUFF
324 bd = QBM_DES_GET_DATAPTR(gpd);
325 EXT_ASSERT(NULL!=bd, (kal_uint32) bd, (kal_uint32) gpd, 0);
326 data_ptr = QBM_DES_GET_DATAPTR(bd);
327 }else{
328 //4 <case 2> GPD->BUFF
329 data_ptr = QBM_DES_GET_DATAPTR(gpd);
330 }
331
332 //Note: This API is also used in exception mode
333 //In exception mode, DHL may directly dump memory address 0x0 (use 0x0 as data buffer address)
334 if(INT_QueryExceptionStatus() == KAL_FALSE)
335 {
336 EXT_ASSERT(NULL!=data_ptr, (kal_uint32) data_ptr, (kal_uint32) bd, (kal_uint32) gpd);
337 }
338 return data_ptr;
339}
340
341/*!
342 * @function [INLINE] CCCIDEV_GET_GPD_LIST_SIZE
343 * @brief Traverse the GPD chain to obtain the number of GPDs in GPD chain.
344 *
345 * @param head [IN] pointer to the head of the GPD chain
346 * @param tail [IN] pointer to the tail of the GPD chain
347 *
348 * @return Number of the GPDs in GPD chain.
349 */
350static __inline kal_uint32 CCCIDEV_GET_GPD_LIST_SIZE(qbm_gpd *head, qbm_gpd *tail)
351{
352 kal_uint32 cnt = 0;
353
354 if (tail) {
355 while (head) {
356 cnt++;
357 if (head != tail) {
358 head = QBM_DES_GET_NEXT(head);
359 } else {
360 break;
361 }
362 }
363 }
364
365 return cnt;
366}
367
368/*!
369 * @function [INLINE] CCCIDEV_GET_NONBPS_GPD_LIST_SIZE
370 * @brief Traverse the GPD chain to obtain the number of NON-bypass GPDs in GPD chain.
371 *
372 * @param head [IN] pointer to the head of the GPD chain
373 * @param tail [IN] pointer to the tail of the GPD chain
374 *
375 * @return Number of the non-bypass GPDs in GPD chain.
376 */
377static __inline kal_uint32 CCCIDEV_GET_NONBPS_GPD_LIST_SIZE(qbm_gpd *head, qbm_gpd *tail)
378{
379 kal_uint32 cnt = 0;
380
381 if (tail) {
382 while (head) {
383 cnt += (0 == QBM_DES_GET_BPS(head));
384 if (head != tail) {
385 head = QBM_DES_GET_NEXT(head);
386 } else {
387 break;
388 }
389 }
390 }
391
392 return cnt;
393}
394
395/*!
396 * @function [INLINE] CCCIDEV_PUSH_QBM_DATAHEAD
397 * @brief Push the Tx GPD/BD data pointer. i.e. increase the header room
398 * 1. move the GPD->1st_BD->data / GPD->data pointer back "offset"
399 * 2. increase the BD length
400 * 3. DO NOT flush the Tx BD header -> QMU enqueue should do it
401 * Please refer to the mail 20120606 from YiLun
402 * > Folder: 0WCP\0. important announce\programming related
403 * > [Note] CACHE op convention : upper user no need to take TX GPD/BD cache flush(clean)
404 * 4. set gpd data length
405 * 5. DO NOT flush the Tx GPD header -> QMU enqueue should do it
406 * reference : ETHC_CORE_PUSH_QBM_DATAHEAD
407 *
408 * @param gpd [IN] pointer to the GPD need modification
409 * @param offset [IN] move the data_ptr by offset
410 *
411 * @return void
412 */
413static __inline void CCCIDEV_PUSH_QBM_DATAHEAD(void* gpd, kal_uint32 offset)
414{
415 void* bd = NULL;
416 kal_uint8* data_ptr = NULL;
417 kal_uint32 data_len = 0;
418
419 if(0 != QBM_DES_GET_BDP(gpd)){
420 //4 <case 1> GPD->BD->BUFF
421 /* set bd data ptr */
422 bd = QBM_DES_GET_DATAPTR(gpd);
423 data_ptr = (kal_uint8*)QBM_DES_GET_DATAPTR(bd);
424 QBM_DES_SET_DATAPTR(bd, data_ptr-offset);
425 /* set bd data len */
426 data_len = QBM_DES_GET_DATALEN(bd);
427 QBM_DES_SET_DATALEN(bd, data_len+offset);
428 /* set bd checksum */
429 qbm_cal_set_checksum(bd);
430
431 /* set gpd data len */
432 data_len = QBM_DES_GET_DATALEN(gpd);
433 QBM_DES_SET_DATALEN(gpd, data_len+offset);
434 /* set gpd checksum */
435 //qbm_cal_set_checksum(gpd);
436 }else{
437 //4 <case 2> GPD->BUFF
438 /* set gpd data ptr */
439 data_ptr = (kal_uint8*)QBM_DES_GET_DATAPTR(gpd);
440 QBM_DES_SET_DATAPTR(gpd, data_ptr-offset);
441 /* set gpd data len */
442 data_len = QBM_DES_GET_DATALEN(gpd);
443 QBM_DES_SET_DATALEN(gpd, data_len+offset);
444 /* set gpd checksum */
445 //qbm_cal_set_checksum(gpd);
446 }
447}
448
449/*!
450 * @function [INLINE] CCCIDEV_PULL_QBM_DATAHEAD
451 * @brief Pull the Tx GPD/BD data pointer. i.e. decrease the header room
452 *
453 * <Used in non-network GPD->BD->BUFF >
454 *
455 * @param gpd [IN] pointer to the GPD need modification
456 * @param offset [IN] move the data_ptr by offset
457 *
458 * @return void
459 */
460static __inline void CCCIDEV_PULL_QBM_DATAHEAD(void* gpd, kal_uint32 offset)
461{
462 void* bd = NULL;
463 kal_uint8* data_ptr = NULL;
464 kal_uint32 data_len = 0;
465
466 if(0 != QBM_DES_GET_BDP(gpd)){
467 //4 <case 1> GPD->BD->BUFF
468 /* set bd data ptr */
469 bd = QBM_DES_GET_DATAPTR(gpd);
470 data_ptr = (kal_uint8*)QBM_DES_GET_DATAPTR(bd);
471 QBM_DES_SET_DATAPTR(bd, data_ptr+offset);
472 /* set bd data len */
473 data_len = QBM_DES_GET_DATALEN(bd);
474 QBM_DES_SET_DATALEN(bd, data_len-offset);
475 /* set bd checksum */
476 qbm_cal_set_checksum(bd);
477 QBM_CACHE_FLUSH_NO_DSR(bd, sizeof(qbm_gpd));
478
479 /* set gpd data len */
480 data_len = QBM_DES_GET_DATALEN(gpd);
481 QBM_DES_SET_DATALEN(gpd, data_len-offset);
482 /* set gpd checksum */
483 qbm_cal_set_checksum(gpd);
484 QBM_CACHE_FLUSH_NO_DSR(gpd, sizeof(qbm_gpd));
485 }else{
486 //4 <case 2> GPD->BUFF
487 /* set gpd data ptr */
488 data_ptr = (kal_uint8*)QBM_DES_GET_DATAPTR(gpd);
489 QBM_DES_SET_DATAPTR(gpd, data_ptr+offset);
490 /* set gpd data len */
491 data_len = QBM_DES_GET_DATALEN(gpd);
492 QBM_DES_SET_DATALEN(gpd, data_len-offset);
493 /* set bd checksum */
494 qbm_cal_set_checksum(gpd);
495 QBM_CACHE_FLUSH_NO_DSR(gpd, sizeof(qbm_gpd));
496 }
497 QBM_DSR();
498}
499
500/*!
501 * @function [INLINE] CCCIDEV_QBM_ENQ
502 * @brief Enqueue p_new_head/p_new_tail to pp_orig_head/pp_orig_tail
503 *
504 * @param p_new_head [IN] head of new gpd chain
505 * @param p_new_tail [IN] tail of new gpd chain
506 * @param pp_orig_head [IN/OUT] head of original gpd chain
507 * @param pp_orig_tail [IN/OUT] tail of original gpd chain
508 *
509 * @return void
510 */
511static __inline void CCCIDEV_QBM_ENQ(void *p_new_head, void *p_new_tail, void **pp_orig_head, void **pp_orig_tail)
512{
513 kal_uint8 *p_ori_tail;
514 p_ori_tail = *pp_orig_tail;
515
516 if(*pp_orig_head == NULL){
517 *pp_orig_tail = p_new_tail;
518 *pp_orig_head = p_new_head;
519 }else{
520 /* link new queue */
521 QBM_DES_SET_NEXT(p_ori_tail, p_new_head);
522 // change tail to new tail
523 *pp_orig_tail = p_new_tail;
524 }
525 QBM_DES_SET_NEXT(*pp_orig_tail, NULL);
526}
527
528/*!
529 * @function [INLINE] CCCIDEV_QBM_DEQ
530 * @brief dequeue n GPD from pp_src_head/pp_src_tail to p_new_head/p_new_tail
531 * a accelerate version of qbmt_de_q_n
532 *
533 * @param pp_src_head [IN/OUT] head of src gpd chain
534 * @param pp_src_tail [IN/OUT] tail of src gpd chain
535 * @param n [IN] dequeue count
536 * @param pp_new_head [OUT] head of dest gpd chain
537 * @param pp_new_tail [OUT] tail of dest gpd chain
538 *
539 * @return void
540 */
541static __inline kal_uint32 CCCIDEV_QBM_DEQ(
542 void **pp_src_head,
543 void **pp_src_tail,
544 kal_uint32 n,
545 void **pp_new_head,
546 void **pp_new_tail
547 )
548{
549 kal_uint32 deq_num = 0;
550
551 if(0 == n){
552 *pp_new_head = NULL;
553 *pp_new_tail = NULL;
554 return 0;
555 }
556
557 if(NULL == *pp_src_head){
558 EXT_ASSERT(NULL == *pp_src_tail, (kal_uint32)*pp_src_head, (kal_uint32) *pp_src_tail, 0);
559 *pp_new_head = NULL;
560 *pp_new_tail = NULL;
561 return 0;
562 }
563
564 *pp_new_head = *pp_src_head;
565
566
567 //for(deq_num = 0; deq_num < n; deq_num++){
568 do{
569 *pp_new_tail = *pp_src_head;
570 deq_num++;
571 *pp_src_head = QBM_DES_GET_NEXT(*pp_src_head);
572 }while((deq_num < n) && (NULL != *pp_src_head));
573
574 if(NULL == *pp_src_head){
575 *pp_src_tail = NULL;
576 }
577
578 return deq_num;
579}
580
581/*!
582 * @function [INLINE] CCCIDEV_FIX_IOR_NULL_LAST
583 * @brief if the last gpd of ior is == NULL, traverse the GPD chain to fill the last_gpd info
584 *
585 * @param ior [IN] input ior
586 *
587 * @return void
588 */
589static __inline void CCCIDEV_FIX_IOR_NULL_LAST(ccci_io_request_t* ior)
590{
591 qbm_gpd *last_gpd = ior->last_gpd;
592 qbm_gpd *first_gpd = ior->first_gpd;
593 qbm_gpd *current_gpd;
594
595 /* fix the last_gpd == NULL case */
596 if (last_gpd == NULL)
597 {
598 current_gpd = first_gpd;
599 while ( current_gpd->p_next != NULL )
600 {
601 current_gpd = current_gpd->p_next;
602 }
603 ior->last_gpd = current_gpd;
604 }
605}
606
607
608/*!
609 * @function [INLINE] CCCIDEV_RM_CCCI_HEADERS
610 * @brief Tool function to remove the CCCI header in GPD->BD->BUFF / GPD->BUFF
611 *
612 * @param channel [IN] channel number for this CCCI header
613 * @param gpd [IN] pointer to the gpd
614 *
615 * @return KAL_TRUE: success, KAL_FALSE: channel number not matched
616 */
617static __inline kal_bool CCCIDEV_RM_CCCI_HEADERS(CCCI_CHANNEL_T channel, qbm_gpd *gpd)
618{
619 CCCI_BUFF_T *pdata;
620
621 //4 <1> check gpd->bd->buff->channel = channel
622 pdata = CCCIDEV_GET_QBM_DATAPTR(gpd);
623 EXT_ASSERT(pdata, (kal_uint32)pdata, (kal_uint32)gpd, (kal_uint32)channel);
624
625 /* treat channel not match and size = 0 as invalid GPD*/
626 if(pdata->channel != channel || pdata->data[1] == sizeof(CCCI_BUFF_T)){
627 //hif_trace_error(CCCIDEV_TR_UL_CCCI_CH_ERR, pdata->channel, channel);
628 return KAL_FALSE;
629 }else{
630 //4 <2> move data pointer to raw data
631 CCCIDEV_PULL_QBM_DATAHEAD(gpd, sizeof(CCCI_BUFF_T));
632 }
633
634 return KAL_TRUE;
635}
636
637/*!
638 * @function [INLINE] ccci_dest_ior
639 * @brief Traverse ior chain to free the linked ior/GPD/BD/Buff
640 *
641 * @param ior [IN] pointer to the ior chain
642 *
643 * @return void
644 */
645static __inline void ccci_dest_ior(ccci_io_request_t *ior){
646 ccci_io_request_t *next_ior;
647 qbm_gpd* current_gpd;
648
649 EXT_ASSERT(ior, (kal_uint32)ior, 0, 0);
650 for (; ior; ior = next_ior) {
651 next_ior = ior->next_request;
652 EXT_ASSERT(ior->first_gpd, (kal_uint32)ior->first_gpd, (kal_uint32)ior, (kal_uint32)next_ior);
653
654 /* fix the last_gpd == NULL case */
655 if (ior->last_gpd == NULL)
656 {
657 current_gpd = ior->first_gpd;
658 while ( current_gpd->p_next != NULL )
659 {
660 current_gpd = current_gpd->p_next;
661 }
662 ior->last_gpd = current_gpd;
663 }
664
665 EXT_ASSERT(ior->first_gpd && ior->last_gpd, (kal_uint32)ior->first_gpd, (kal_uint32)ior->last_gpd, (kal_uint32)ior);
666 qbmt_dest_q(ior->first_gpd, ior->last_gpd);
667 }
668}
669
670/* Get address by a offset of the PD */
671#define CCCIDEV_QBM_DES_GET_ADDR_BY_OFFSET(_p, _ofst) \
672 (void*)((kal_uint8*)(_p) + (_ofst))
673
674/* Used for buffer and descriptor are in continus memory address */
675#define CCCIDEV_QBM_DES_SET_DATA_BY_OFFSET(_p, _ofst) \
676 (QBM_GET_GPD_PTR(_p)->p_data_tbd = CCCIDEV_QBM_DES_GET_ADDR_BY_OFFSET(_p, _ofst))
677
678#define CCCI_COMM_BD_OFST (64) /* p_data_tbd = 64 */
679#define CCCI_COMM_GET_BD(_p) CCCIDEV_QBM_DES_GET_ADDR_BY_OFFSET(_p, CCCI_COMM_BD_OFST)
680
681/* this code will set datalen and extlen to 0 */
682/* Because in descriptor, they are in the 12 bytes */
683#define CCCI_COMM_RESET_DATALEN_EXTLEN(_p) *(kal_uint32*)((kal_uint8*)(_p) + 12) = 0
684
685/*!
686 * @function [INLINE] CCCIDEV_RST_CCCI_COMM_GPD_LIST
687 * @brief Reset the GPD list to the default value, type has to be QBM_TYPE_CCCI_COMM
688 *
689 * @param first_gpd [IN] pointer to the first GPD in the GPD chain
690 * @param last_gpd [IN] pointer to the last GPD in the GPD chain
691 *
692 * @return void
693 */
694static __inline kal_uint32 CCCIDEV_RST_CCCI_COMM_GPD_LIST(qbm_gpd* first_gpd, qbm_gpd* last_gpd)
695{
696 qbm_gpd* current_gpd = NULL;
697 qbm_gpd* next_gpd = NULL;
698 kal_uint32 num_gpd = 0;
699
700 EXT_ASSERT(first_gpd && last_gpd, (kal_uint32)first_gpd, (kal_uint32)last_gpd, 0);
701 current_gpd = first_gpd;
702
703 do {
704 next_gpd = QBM_DES_GET_NEXT(current_gpd);
705 qbm_reset_pd(QBM_TYPE_CCCI_COMM, (void*)current_gpd);
706 qbm_cal_set_checksum((kal_uint8 *)current_gpd);
707 QBM_CACHE_FLUSH_NO_DSR(current_gpd, sizeof(qbm_gpd));
708 num_gpd ++;
709 if ( current_gpd == last_gpd )
710 {
711 break;
712 }
713 current_gpd = next_gpd;
714 } while ( current_gpd != NULL );
715 QBM_DSR();
716 return num_gpd;
717}
718
719/*!
720 * @function [Prototype] cccidev_dl_header_handle_cb
721 * @brief Prototype of function to handle each packet's CCCI Header
722 *
723 * @param pDevice [IN] pointer to the CCCIDEV device
724 * @param p_ccci_head [IN] pointer to ccci header buffer
725 * @param kal_uint8 [IN] pointer to the data buffer
726 *
727 * @return 0, unused
728 */
729typedef kal_uint32 (*cccidev_dl_header_handle_cb)(void* p_device, CCCI_BUFF_T* p_ccci_head, kal_uint8* pdata, kal_uint32 data_len);
730
731/*!
732 * @function [static] CCCIDEV_SPD_PI_RELAYOUT
733 * @brief Traverse the input GPD list and insert the CCCI header on the first BD->data
734 *
735 * @param spd [IN] pointer to the SPD in the GPD chain
736 *
737 * @return relayout success
738 */
739static __inline kal_uint32 CCCIDEV_SPD_PI_RELAYOUT(qbm_gpd* p_spd){
740 hif_spd_ext_header *p_spd_ext = (hif_spd_ext_header*)QBM_SPD_GET_EXT((qbm_spd*)p_spd);
741 hif_spd_packet_header *p_spd_ph;
742 qbm_spd_pie *p_spd_pie;
743 qbm_spd_pi *p_spd_pi = QBM_SPD_GET_PI((qbm_spd*)p_spd);
744 kal_uint16 i, pkt_num = 0, header_len = sizeof(CCCI_BUFF_T);
745
746 EXT_ASSERT(QBM_DES_GET_PDT(p_spd) == DES_FLAG_BIT_SPD3,QBM_DES_GET_PDT(p_spd), (kal_uint32)p_spd, 0);
747 p_spd_pie = QBM_SPD_PI_GET_FIRST_PIE(p_spd_pi);
748 p_spd_ph = HIF_SPD_EXT_GET_FIRST_PH(p_spd_ext);
749 pkt_num = QBM_SPD_PI_GET_PKTNUM(p_spd_pi);
750 HIF_SPD_EXT_SET_PKTNUM(p_spd_ext, pkt_num);
751 HIF_SPD_EXT_SET_SPD1_HEADERLEN(p_spd_ext , (kal_uint8)header_len);
752#ifdef CCCIDEV_SPD_RELAYOUT_SET_PKTNUM_TRACE
753 if(KAL_TRUE != kal_query_systemInit() && KAL_FALSE == INT_QueryExceptionStatus())
754 CCCIDEV_SPD_RELAYOUT_SET_PKTNUM_TRACE(pkt_num, (kal_uint32) p_spd_pi, (kal_uint32) p_spd_ext);
755#endif
756 QBM_DES_SET_SPD1(p_spd);
757 for(i = 1; i <=pkt_num; i++){
758 kal_mem_cpy(p_spd_ph, p_spd_pie, sizeof(qbm_spd_pie));
759 // @This is the last packet : check if EPDCP set the EOL correctly, if this assert happend, please contact EPDCP owner
760 if (i == pkt_num){
761 EXT_ASSERT(HIF_SPD_PH_GET_EOL(p_spd_ph), \
762 (kal_uint32)p_spd, pkt_num, (kal_uint32)p_spd_ph);
763 }
764 // @This is an EOL packet : if get EOL but not last packet, should break, no need to handle remaining packet
765 else if (HIF_SPD_PH_GET_EOL(p_spd_ph)){
766#ifdef CCCIDEV_SPD_RELAYOUT_GET_EOL_BREAK_TRACE
767 if(KAL_TRUE != kal_query_systemInit() && KAL_FALSE == INT_QueryExceptionStatus())
768 CCCIDEV_SPD_RELAYOUT_GET_EOL_BREAK_TRACE(pkt_num, i, (kal_uint32) p_spd_ph);
769#endif
770 break;
771 }
772 // @This is a normal packet : if get not last GPD, move to next ph
773 else{
774 p_spd_ph = HIF_SPD_PH_NEXT(p_spd_ph, (kal_uint8)header_len);
775 p_spd_pie = QBM_SPD_PIE_NEXT(p_spd_pie);
776 }
777 }
778 return 0;
779}
780
781
782/*!
783 * @function [static] CCCIDEV_PROCESS_DL_GPD_LIST
784 * @brief Traverse the input GPD list and insert the CCCI header on the first BD->data
785 *
786 * @param pDevice [IN] pointer to the CCCIDEV device
787 * @param first_gpd [IN] pointer to the first GPD in the GPD chain
788 * @param last_gpd [IN] pointer to the last GPD in the GPD chain
789 * @param cccidev_dl_header_handle_cb [IN] pointer of the callback function to handle each packet's CCCI Header
790 *
791 * @return number of gpd/spd in between first_gpd and last_gpd
792 */
793static __inline kal_uint32 CCCIDEV_PROCESS_DL_GPD_LIST(void* pDevice, qbm_gpd* first_gpd, qbm_gpd* last_gpd, cccidev_dl_header_handle_cb cb)
794{ /*process_tx_gpd_list*/
795 qbm_gpd* p_gpd = NULL;
796 kal_uint32 gpd_cnt = 0;
797 CCCI_BUFF_T *p_ccci_head;
798 kal_uint8 current_pdt;
799 hif_spd_packet_header *p_spd_ph, *p_spd_ph_next=NULL; //spd packet head
800 kal_uint8 *p_payload, *p_payload_next=NULL; //spd packet payload
801 hif_spd_ext_header *p_spd_ext; //spd extention
802 kal_uint16 pkt_num;
803 kal_uint32 i, payload_len, header_len=0;
804 kal_uint32 data_len = 0;
805 EXT_ASSERT(first_gpd && last_gpd, (kal_uint32)first_gpd, (kal_uint32)last_gpd, (kal_uint32)pDevice);
806
807 p_gpd = first_gpd;
808 do {
809 current_pdt = QBM_DES_GET_PDT(p_gpd);
810 if(current_pdt == DES_FLAG_BIT_SPD3){
811 CCCIDEV_SPD_PI_RELAYOUT(p_gpd);
812 current_pdt = QBM_DES_GET_PDT(p_gpd);
813 }
814
815 EXT_ASSERT((( current_pdt == DES_FLAG_BIT_SPD1) || (current_pdt == DES_FLAG_BIT_GPD)), \
816 (kal_uint32)current_pdt, (kal_uint32)pDevice, (kal_uint32)p_gpd);
817
818 if(current_pdt == DES_FLAG_BIT_SPD1){
819 //4 <1> SPD1 handling
820 p_spd_ext = (hif_spd_ext_header*)QBM_SPD_GET_EXT((qbm_spd*)p_gpd);
821 p_spd_ph = HIF_SPD_EXT_GET_FIRST_PH((hif_spd_ext_header*)p_spd_ext);
822 p_payload = QBM_DES_GET_DATAPTR((qbm_spd*)p_gpd);
823 pkt_num = HIF_SPD_EXT_GET_PKTNUM((hif_spd_ext_header*)p_spd_ext);
824 //[tk6291_mw_hif_spd_design_doc_v1.0: The packet number should be larger than 1
825 EXT_ASSERT(pkt_num >= 1, pkt_num, (kal_uint32)p_spd_ext, (kal_uint32)(qbm_spd*)p_gpd);
826
827 //4 <1.1> set spd1_header_len = sizeof(CCCI_BUFF_T);
828 //Header length fill by first user
829 header_len = HIF_SPD_EXT_GET_SPD1_HEADERLEN((hif_spd_ext_header*)p_spd_ext);
830 p_spd_ph_next = HIF_SPD_PH_NEXT(p_spd_ph, header_len); // initial
831#ifdef CCCIDEV_PROCESS_DL_SPD_TRACE
832 if(KAL_TRUE != kal_query_systemInit() && KAL_FALSE == INT_QueryExceptionStatus())
833 CCCIDEV_PROCESS_DL_SPD_TRACE(pkt_num, (kal_uint32)p_gpd);
834#endif
835 //4 <1.2> Set IGR for 1st pkt, for MBIM use only, and move to 2nd PH
836 //iterate from the 1st ph
837 for (i=1; i<=pkt_num; i++){
838 payload_len = HIF_SPD_PH_GET_PAYLOAD_LEN(p_spd_ph);
839 if (i != pkt_num){
840 p_spd_ph_next = HIF_SPD_PH_NEXT(p_spd_ph, header_len);
841 p_payload_next = QBM_SPD_PAYLOAD_NEXT(p_payload, payload_len);
842 }
843 if(0 == HIF_SPD_PH_GET_IGR(p_spd_ph)){ // if IGR bit is not set
844 //4 <1.3> append CCCI header CCCI_BUFF_T
845 p_ccci_head = (CCCI_BUFF_T *)HIF_SPD_PH_GET_HEADER(p_spd_ph);
846 // call CCCI Device CCCI header handle
847 cb(pDevice, p_ccci_head, p_payload, payload_len);
848 // payload length check, if this assert happend, please contact EPDCP owner
849 EXT_ASSERT(payload_len, \
850 (kal_uint32)p_gpd, pkt_num, (kal_uint32)p_spd_ph);
851 }
852 else{ // if IGR bit is set
853#ifdef CCCIDEV_PROCESS_DL_SPD_SET_IGR_TRACE
854 if(KAL_TRUE != kal_query_systemInit() && KAL_FALSE == INT_QueryExceptionStatus())
855 CCCIDEV_PROCESS_DL_SPD_SET_IGR_TRACE(HIF_SPD_PH_GET_IGR(p_spd_ph), i, (kal_uint32)p_spd_ph);
856#endif
857 }
858 // @This is the last packet : check if EPDCP set the EOL correctly, if this assert happend, please contact EPDCP owner
859 if (i == pkt_num)
860 {
861 EXT_ASSERT(HIF_SPD_PH_GET_EOL(p_spd_ph), \
862 (kal_uint32)p_gpd, pkt_num, (kal_uint32)p_spd_ph);
863 QBM_CACHE_FLUSH(p_spd_ext, sizeof(qbm_spd_ext));
864 }
865 // @This is an EOL packet :if get EOL but not last packet, should breakm, no need to handle remaining packet
866 else if (HIF_SPD_PH_GET_EOL(p_spd_ph)){
867#ifdef CCCIDEV_SPD_RELAYOUT_GET_EOL_BREAK_TRACE
868 if(KAL_TRUE != kal_query_systemInit() && KAL_FALSE == INT_QueryExceptionStatus())
869 CCCIDEV_SPD_RELAYOUT_GET_EOL_BREAK_TRACE(pkt_num, i, (kal_uint32) p_spd_ph);
870#endif
871 QBM_CACHE_FLUSH(p_spd_ext, sizeof(qbm_spd_ext));
872 break;
873 }
874 // @This is a normal packet : if get not last GPD, move to next ph
875 else
876 {
877 p_spd_ph = p_spd_ph_next;
878 p_payload = p_payload_next;
879 }
880 }
881 }else
882 {
883 //4 <2> GPD handling
884 /* ASSERT if not GPD type, if this assert happens meaning DL is neither SPD type1 nor GPD
885 please seek for EPDCP owner's help*/
886 EXT_ASSERT((current_pdt == DES_FLAG_BIT_GPD), \
887 (kal_uint32)current_pdt, (kal_uint32)pDevice, (kal_uint32)p_gpd);
888
889 //4 <2.1> append CCCI header CCCI_BUFF_T
890 // CCCIDEV append ccci header in BD EXT(only for CCMNI with first empty BD) or GPD EXT
891 if((0 != QBM_DES_GET_BDP(p_gpd)) && (0 == QBM_DES_GET_DATALEN (QBM_DES_GET_DATAPTR(p_gpd)))){
892 //4 <case 1> GPD->BD->BUFF
893 /* Store the DL CCCI header in the BD extention part */
894 void* bd = QBM_DES_GET_DATAPTR(p_gpd);
895 QBM_DES_SET_EXTLEN(bd, sizeof(CCCI_BUFF_T));
896 p_ccci_head = (CCCI_BUFF_T *)QBM_DES_GET_EXT(bd);
897 qbm_cal_set_checksum(bd);
898 QBM_CACHE_FLUSH(bd, sizeof(qbm_gpd));
899 QBM_DES_SET_DATALEN(p_gpd, CCCIDEV_GET_QBM_DATALEN(p_gpd)+sizeof(CCCI_BUFF_T));
900 data_len = CCCIDEV_GET_QBM_DATALEN(p_gpd);
901 }
902 else{
903 //4 <case 2> GPD->BUFF
904 /* Store the DL CCCI header in the GPD extention part */
905 QBM_DES_SET_EXTLEN(p_gpd, sizeof(CCCI_BUFF_T));
906 p_ccci_head = (CCCI_BUFF_T *)QBM_DES_GET_EXT(p_gpd);
907 data_len = CCCIDEV_GET_QBM_DATALEN(p_gpd) + sizeof(CCCI_BUFF_T);
908 }
909 p_payload = CCCIDEV_GET_QBM_DATAPTR(p_gpd);
910 // call CCCI Device CCCI header handle
911 cb(pDevice, p_ccci_head, p_payload, data_len);
912
913 }
914 gpd_cnt++;
915 if ( p_gpd == last_gpd )
916 {
917 break;
918 }
919 //make sure there is no invalid GPD in the list
920 EXT_ASSERT(QBM_DES_GET_NEXT(p_gpd) != NULL, (kal_uint32)p_gpd, (kal_uint32)first_gpd, (kal_uint32)last_gpd);
921 p_gpd = QBM_DES_GET_NEXT(p_gpd);
922 } while ( p_gpd != NULL );
923 return gpd_cnt;
924}
925
926/*!
927 * @function [Prototype] cccidev_dl_header_handle_cb
928 * @brief Prototype of function to handle each packet's CCCI Header
929 *
930 * @param pDevice [IN] pointer to the CCCIDEV device
931 * @param p_ccci_head [IN] pointer to ccci header buffer
932 * @param kal_uint8 [IN] pointer to the data buffer
933 *
934 * @return 0, unused
935 */
936typedef 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);
937
938/*!
939 * @function [static] CCCIDEV_PROCESS_DL_GPD_LIST
940 * @brief Traverse the input GPD list and insert the CCCI header on the first BD->data
941 *
942 * @param pDevice [IN] pointer to the CCCIDEV device
943 * @param first_gpd [IN] pointer to the first GPD in the GPD chain
944 * @param last_gpd [IN] pointer to the last GPD in the GPD chain
945 * @param cccidev_dl_header_handle_cb [IN] pointer of the callback function to handle each packet's CCCI Header
946 *
947 * @return number of gpd/spd in between first_gpd and last_gpd
948 */
949static __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)
950{ /*process_tx_gpd_list*/
951 qbm_gpd* p_gpd = NULL;
952 kal_uint32 gpd_cnt = 0;
953 CCCI_BUFF_T *p_ccci_head;
954 kal_uint8 current_pdt;
955 hif_spd_packet_header *p_spd_ph, *p_spd_ph_next=NULL; //spd packet head
956 kal_uint8 *p_payload, *p_payload_next=NULL; //spd packet payload
957 hif_spd_ext_header *p_spd_ext; //spd extention
958 kal_uint16 pkt_num;
959 kal_uint32 i, payload_len, header_len =0;
960 kal_bool is_first_SPD = KAL_TRUE;
961
962 EXT_ASSERT(first_gpd && last_gpd, (kal_uint32)first_gpd, (kal_uint32)last_gpd, (kal_uint32)pDevice);
963
964 p_gpd = first_gpd;
965 do {
966 current_pdt = QBM_DES_GET_PDT(p_gpd);
967 if(current_pdt == DES_FLAG_BIT_SPD3){
968 CCCIDEV_SPD_PI_RELAYOUT(p_gpd);
969 current_pdt = QBM_DES_GET_PDT(p_gpd);
970 }
971
972 EXT_ASSERT((( current_pdt == DES_FLAG_BIT_SPD1) || (current_pdt == DES_FLAG_BIT_GPD)), \
973 (kal_uint32)current_pdt, (kal_uint32)pDevice, (kal_uint32)p_gpd);
974
975 if(current_pdt == DES_FLAG_BIT_SPD1)
976 {
977 p_spd_ext = (hif_spd_ext_header*)QBM_SPD_GET_EXT((qbm_spd*)p_gpd);
978 p_spd_ph = HIF_SPD_EXT_GET_FIRST_PH((hif_spd_ext_header*)p_spd_ext);
979 p_spd_ph_next = HIF_SPD_PH_NEXT(p_spd_ph, 0); //initial
980 p_payload = QBM_DES_GET_DATAPTR((qbm_spd*)p_gpd);
981 pkt_num = HIF_SPD_EXT_GET_PKTNUM((hif_spd_ext_header*)p_spd_ext);
982 //[tk6291_mw_hif_spd_design_doc_v1.0: The packet number should be larger than 1
983 EXT_ASSERT(pkt_num >= 1, pkt_num, (kal_uint32)p_spd_ext, (kal_uint32)(qbm_spd*)p_gpd);
984
985 //4 <1.1> set spd1_header_len = sizeof(CCCI_BUFF_T);
986 //Header length fill by first user
987 header_len = HIF_SPD_EXT_GET_SPD1_HEADERLEN((hif_spd_ext_header*)p_spd_ext);
988#ifdef CCCIDEV_PROCESS_DL_SPD_TRACE
989 if(KAL_TRUE != kal_query_systemInit() && KAL_FALSE == INT_QueryExceptionStatus())
990 CCCIDEV_PROCESS_DL_SPD_TRACE(pkt_num, (kal_uint32)p_gpd);
991#endif
992 //4 <1.2> Set IGR for 1st pkt, for MBIM use only, and move to 2nd PH
993 //iterate from the 1st ph
994 if(is_first_SPD == KAL_TRUE){ // only add CCCI header to first SPD
995 is_first_SPD = KAL_FALSE;
996 for (i=1; i<=pkt_num; i++){
997 payload_len = HIF_SPD_PH_GET_PAYLOAD_LEN(p_spd_ph);
998 if (i != pkt_num){
999 p_spd_ph_next = HIF_SPD_PH_NEXT(p_spd_ph, header_len);
1000 p_payload_next = QBM_SPD_PAYLOAD_NEXT(p_payload, payload_len);
1001 }
1002 if(0 == HIF_SPD_PH_GET_IGR(p_spd_ph)){ // if IGR bit is not set
1003 //4 <1.3> append CCCI header CCCI_BUFF_T
1004 p_ccci_head = (CCCI_BUFF_T *)HIF_SPD_PH_GET_HEADER(p_spd_ph);
1005 // call CCCI Device CCCI header handle
1006 cb(pDevice, p_ccci_head, p_payload, payload_len, rem_gpd);
1007 // This is SPD mode
1008 if(rem_gpd > 0)
1009 p_ccci_head->data[1] = p_ccci_head->data[1] | (1 << 31);
1010 // payload length check, if this assert happend, please contact EPDCP owner
1011 EXT_ASSERT(payload_len, \
1012 (kal_uint32)p_gpd, pkt_num, (kal_uint32)p_spd_ph);
1013 break;//only handle first header
1014 }
1015 else{ // if IGR bit is set
1016#ifdef CCCIDEV_PROCESS_DL_SPD_SET_IGR_TRACE
1017 if(KAL_TRUE != kal_query_systemInit() && KAL_FALSE == INT_QueryExceptionStatus())
1018 CCCIDEV_PROCESS_DL_SPD_SET_IGR_TRACE(HIF_SPD_PH_GET_IGR(p_spd_ph), i, (kal_uint32)p_spd_ph);
1019#endif
1020 }
1021 // @This is a normal packet : if get not last GPD, move to next ph
1022 //else
1023 {
1024 p_spd_ph = p_spd_ph_next;
1025 p_payload = p_payload_next;
1026 }
1027 }
1028 }
1029 // Flush all spd ext
1030 QBM_CACHE_FLUSH(p_spd_ext, sizeof(qbm_spd_ext));
1031 }
1032 else
1033 {
1034 //4 <2> GPD handling
1035 /* ASSERT if not GPD type, if this assert happens meaning DL is neither SPD type1 nor GPD
1036 please seek for EPDCP owner's help*/
1037 EXT_ASSERT((current_pdt == DES_FLAG_BIT_GPD), \
1038 (kal_uint32)current_pdt, (kal_uint32)pDevice, (kal_uint32)p_gpd);
1039
1040 //4 <2.1> append CCCI header CCCI_BUFF_T
1041 // CCCIDEV append ccci header in BD EXT(only for CCMNI with first empty BD) or GPD EXT
1042 if((0 != QBM_DES_GET_BDP(p_gpd)) && (0 == QBM_DES_GET_DATALEN (QBM_DES_GET_DATAPTR(p_gpd)))){
1043 //4 <case 1> GPD->BD->BUFF
1044 /* Store the DL CCCI header in the BD extention part */
1045 void* bd = QBM_DES_GET_DATAPTR(p_gpd);
1046 QBM_DES_SET_EXTLEN(bd, sizeof(CCCI_BUFF_T));
1047 p_ccci_head = (CCCI_BUFF_T *)QBM_DES_GET_EXT(bd);
1048 qbm_cal_set_checksum(bd);
1049 QBM_CACHE_FLUSH(bd, sizeof(qbm_gpd));
1050 QBM_DES_SET_DATALEN(p_gpd, CCCIDEV_GET_QBM_DATALEN(p_gpd)+sizeof(CCCI_BUFF_T));
1051 CCCI_STREAM_SET_LEN(p_ccci_head, CCCIDEV_GET_QBM_DATALEN(p_gpd));
1052 /* hifsdioq_set_gpd will set HWO and set checksum */
1053 //qbm_cal_set_checksum(p_gpd);
1054 //QBM_CACHE_FLUSH(p_gpd, sizeof(qbm_gpd));
1055 }
1056 else{
1057 //4 <case 2> GPD->BUFF
1058 /* Store the DL CCCI header in the GPD extention part */
1059 QBM_DES_SET_EXTLEN(p_gpd, sizeof(CCCI_BUFF_T));
1060 p_ccci_head = (CCCI_BUFF_T *)QBM_DES_GET_EXT(p_gpd);
1061 CCCI_STREAM_SET_LEN(p_ccci_head, CCCIDEV_GET_QBM_DATALEN(p_gpd)+sizeof(CCCI_BUFF_T));
1062 }
1063 p_payload = CCCIDEV_GET_QBM_DATAPTR(p_gpd);
1064 // call CCCI Device CCCI header handle
1065 cb(pDevice, p_ccci_head, p_payload, CCCIDEV_GET_QBM_DATALEN(p_gpd), rem_gpd);
1066 break; // GPD mode only processes first gpd
1067 }
1068 gpd_cnt++;
1069 if ( p_gpd == last_gpd )
1070 {
1071 break;
1072 }
1073 //make sure there is no invalid GPD in the list
1074 EXT_ASSERT(QBM_DES_GET_NEXT(p_gpd) != NULL, (kal_uint32)p_gpd, (kal_uint32)first_gpd, (kal_uint32)last_gpd);
1075 p_gpd = QBM_DES_GET_NEXT(p_gpd);
1076 } while ( p_gpd != NULL );
1077 return gpd_cnt;
1078}
1079
1080#endif //#ifndef _CCCIDEV_QBM_H