xref: /utopia/UTPA2-700.0.x/modules/cmdq/drv/cmdq/drvCMDQ.c (revision 53ee8cc121a030b8d368113ac3e966b4705770ef)
1 //<MStar Software>
2 //******************************************************************************
3 // MStar Software
4 // Copyright (c) 2010 - 2012 MStar Semiconductor, Inc. All rights reserved.
5 // All software, firmware and related documentation herein ("MStar Software") are
6 // intellectual property of MStar Semiconductor, Inc. ("MStar") and protected by
7 // law, including, but not limited to, copyright law and international treaties.
8 // Any use, modification, reproduction, retransmission, or republication of all
9 // or part of MStar Software is expressly prohibited, unless prior written
10 // permission has been granted by MStar.
11 //
12 // By accessing, browsing and/or using MStar Software, you acknowledge that you
13 // have read, understood, and agree, to be bound by below terms ("Terms") and to
14 // comply with all applicable laws and regulations:
15 //
16 // 1. MStar shall retain any and all right, ownership and interest to MStar
17 //    Software and any modification/derivatives thereof.
18 //    No right, ownership, or interest to MStar Software and any
19 //    modification/derivatives thereof is transferred to you under Terms.
20 //
21 // 2. You understand that MStar Software might include, incorporate or be
22 //    supplied together with third party`s software and the use of MStar
23 //    Software may require additional licenses from third parties.
24 //    Therefore, you hereby agree it is your sole responsibility to separately
25 //    obtain any and all third party right and license necessary for your use of
26 //    such third party`s software.
27 //
28 // 3. MStar Software and any modification/derivatives thereof shall be deemed as
29 //    MStar`s confidential information and you agree to keep MStar`s
30 //    confidential information in strictest confidence and not disclose to any
31 //    third party.
32 //
33 // 4. MStar Software is provided on an "AS IS" basis without warranties of any
34 //    kind. Any warranties are hereby expressly disclaimed by MStar, including
35 //    without limitation, any warranties of merchantability, non-infringement of
36 //    intellectual property rights, fitness for a particular purpose, error free
37 //    and in conformity with any international standard.  You agree to waive any
38 //    claim against MStar for any loss, damage, cost or expense that you may
39 //    incur related to your use of MStar Software.
40 //    In no event shall MStar be liable for any direct, indirect, incidental or
41 //    consequential damages, including without limitation, lost of profit or
42 //    revenues, lost or damage of data, and unauthorized system use.
43 //    You agree that this Section 4 shall still apply without being affected
44 //    even if MStar Software has been modified by MStar in accordance with your
45 //    request or instruction for your use, except otherwise agreed by both
46 //    parties in writing.
47 //
48 // 5. If requested, MStar may from time to time provide technical supports or
49 //    services in relation with MStar Software to you for your use of
50 //    MStar Software in conjunction with your or your customer`s product
51 //    ("Services").
52 //    You understand and agree that, except otherwise agreed by both parties in
53 //    writing, Services are provided on an "AS IS" basis and the warranty
54 //    disclaimer set forth in Section 4 above shall apply.
55 //
56 // 6. Nothing contained herein shall be construed as by implication, estoppels
57 //    or otherwise:
58 //    (a) conferring any license or right to use MStar name, trademark, service
59 //        mark, symbol or any other identification;
60 //    (b) obligating MStar or any of its affiliates to furnish any person,
61 //        including without limitation, you and your customers, any assistance
62 //        of any kind whatsoever, or any information; or
63 //    (c) conferring any license or right under any intellectual property right.
64 //
65 // 7. These terms shall be governed by and construed in accordance with the laws
66 //    of Taiwan, R.O.C., excluding its conflict of law rules.
67 //    Any and all dispute arising out hereof or related hereto shall be finally
68 //    settled by arbitration referred to the Chinese Arbitration Association,
69 //    Taipei in accordance with the ROC Arbitration Law and the Arbitration
70 //    Rules of the Association by three (3) arbitrators appointed in accordance
71 //    with the said Rules.
72 //    The place of arbitration shall be in Taipei, Taiwan and the language shall
73 //    be English.
74 //    The arbitration award shall be final and binding to both parties.
75 //
76 //******************************************************************************
77 //<MStar Software>
78 ////////////////////////////////////////////////////////////////////////////////////////////////////
79 //
80 // Copyright (c) 2006-2009 MStar Semiconductor, Inc.
81 // All rights reserved.
82 //
83 // Unless otherwise stipulated in writing, any and all information contained
84 // herein regardless in any format shall remain the sole proprietary of
85 // MStar Semiconductor Inc. and be kept in strict confidence
86 // ("MStar Confidential Information") by the recipient.
87 // Any unauthorized act including without limitation unauthorized disclosure,
88 // copying, use, reproduction, sale, distribution, modification, disassembling,
89 // reverse engineering and compiling of the contents of MStar Confidential
90 // Information is unlawful and strictly prohibited. MStar hereby reserves the
91 // rights to any and all damages, losses, costs and expenses resulting therefrom.
92 //
93 ////////////////////////////////////////////////////////////////////////////////////////////////////
94 
95 ////////////////////////////////////////////////////////////////////////////////////////////////////
96 //
97 // file    drvCMDQ.c
98 // @brief  CMDQ Driver
99 // @author MStar Semiconductor,Inc.
100 //
101 ////////////////////////////////////////////////////////////////////////////////////////////////////
102 #ifdef MSOS_TYPE_LINUX_KERNEL
103 #include <linux/string.h>
104 #else
105 #include <stdio.h>
106 #include <string.h>
107 #include <stdlib.h>
108 #include <string.h>
109 #endif
110 #include "MsCommon.h"
111 #include "MsIRQ.h"
112 #include "MsOS.h"
113 #include "MsVersion.h"
114 
115 #include "drvMMIO.h"
116 #include "halCMDQ.h"
117 #include "drvCMDQ.h"
118 #include "regCMDQ.h"
119 #include "utopia_dapi.h"
120 #include "utopia.h"
121 #include "drvCMDQ_priv.h"
122 
123 #include "halMPool.h"
124 #include "halCHIP.h"
125 
126 #include "ULog.h"
127 //--------------------------------------------------------------------------------------------------
128 //  Global Variable
129 //--------------------------------------------------------------------------------------------------
130 // To replace following shared memory pointer.
131 // cmdq_init, cmdq_miu_select, cmdq_buffer_write_pointer, cmdq_buffer_start, cmdq_buffer_end
132 typedef struct {
133     MS_U32 init;
134     MS_U32 miu_select;
135     MS_PHY buffer_wr;
136     MS_PHY buffer_start;
137     MS_PHY buffer_end;
138 } ShmCtx;
139 
140 /// struct to storing statistical data for profiling and debugging.
141 typedef struct {
142     //to replace count_command_set, record how many commands.
143     MS_U32 cmd_count;
144 
145     //user can set a bunch of commands one time, we record this.
146     MS_U32 cmd_setcount;
147 
148     //counting NULL command that added for padding by drvier. (not by user)
149     MS_U32 cmd_nullcnt;
150 
151 } StatsCtx;
152 
153 typedef struct {
154     //
155     //MS_U32  count_command_set;
156     StatsCtx stats;
157     // only agate will use DIRECT_MODE, but agate will no longer use
158     MS_U32  CMDQ_MODE;
159     //
160     MS_SIZE TOTAL_BUFFER_SIZE;
161     //
162     MS_U32  CMDQ_BUFFER_MIU;
163     // pa, the Buffer_Start Address, no need to be protected, fixed
164     MS_PHY  buffer_start;
165     // pa, the Buffer_End Address, no need to be protected, fixed
166     MS_PHY  buffer_end;
167     // pa, the Write_Pointer for CMDQ Buffer, pointing to the CMDQ Buffer start_addr of
168     // next writing command, need to protected among processes
169     MS_PHY  buffer_wr;
170     // va for buffer_wr, no need to be protected, varied with buffer_wr
171     MS_U8*  buffer_wrptr;
172 
173     MS_S32  mutex;
174     char    *mutex_name; //this name is for MsOS_CreateMutex
175 
176     ShmCtx  *shm;
177     char    *shm_name;   //this id used for MsOS_SHM_GetId
178 } Context;
179 #if (NUMBER_OF_CMDQ_HW == 1)
180 static Context _ctx[NUMBER_OF_CMDQ_HW] = {
181     { {0,0,0}, RING_BUFFER_MODE, 0, 0, 0, 0, 0, NULL, -1, "cmdq0.mutex", NULL, "cmdq0.shm" }
182 };
183 #elif (NUMBER_OF_CMDQ_HW == 2)
184 static Context _ctx[NUMBER_OF_CMDQ_HW] = {
185     { {0,0,0}, RING_BUFFER_MODE, 0, 0, 0, 0, 0, NULL, -1, "cmdq0.mutex", NULL, "cmdq0.shm" },
186     { {0,0,0}, RING_BUFFER_MODE, 0, 0, 0, 0, 0, NULL, -1, "cmdq1.mutex", NULL, "cmdq1.shm" }
187 };
188 #else
189 #endif
190 static MS_U32 IS_STR_RESUME = 0;  // for STR, if suspend to resume, we will set this to be 1, and the init_calls will be done again
191 static DrvCMDQ_DbgLevel _u32CMDQDBGLevel = 0;
192 static MSIF_Version _drv_comq_version = {
193     .DDI = { CMDQ_DRV_VERSION, },
194 };
195 
196 //define mutex(FIX: mutex should remove if utopia2.0)
197 #define CMDQ_MUTEX_CREATE(hnd)          _ctx[hnd].mutex = MsOS_CreateMutex(E_MSOS_FIFO, _ctx[hnd].mutex_name ,MSOS_PROCESS_SHARED)
198 #define CMDQ_MUTEX_LOCK(hnd)            MsOS_ObtainMutex(_ctx[hnd].mutex, MSOS_WAIT_FOREVER)
199 #define CMDQ_MUTEX_UNLOCK(hnd)          MsOS_ReleaseMutex(_ctx[hnd].mutex)
200 #define CMDQ_MUTEX_DELETE(hnd)          MsOS_DeleteMutex(_ctx[hnd].mutex)
201 
202 //physical address to virtual address
203 #define MS_CMDQ2PA(_addr_)           (MS_PHY)MsOS_VA2PA((_addr_))
204 #define MS_PA2KSEG0(_addr_)          (MS_VIRT)MsOS_PA2KSEG0((_addr_))
205 #define MS_PA2KSEG1(_addr_)          (MS_VIRT)MsOS_PA2KSEG1((_addr_))
206 
207 #define CMDQ_FPGA_ASIC_VERIFY        0UL
208 #define MIU_NOT_SUPPORT              2
209 //--------------------------------------------------------------------------------------------------
210 //  Debug Function
211 //--------------------------------------------------------------------------------------------------
212 #define TAG_DRV_CMDQ "DRV_CMDQ"
213 #define DEBUG_CMDQ(debug_level, x)     do { if (_u32CMDQDBGLevel >= (debug_level)) (x); } while(0)
214 
215 #if (defined ANDROID) && (defined TV_OS)
216 #include <cutils/log.h>
217 #define printf LOGD
218 #ifndef LOGD // android 4.1 rename LOGx to ALOGx
219 #define LOGD ALOGD
220 #endif
221 
222 #if 1
223 #define _msg(fmt, ...)
224 #define _dbg(fmt, ...)
225 #define _err(fmt, ...)
226 #define _cri(fmt, ...)
227 #else
228 #define _msg(fmt, ...) do { if(_u32CMDQDBGLevel) LOGD(fmt, ##__VA_ARGS__); } while(0)
229 #define _dbg LOGD
230 #define _err LOGD
231 #define _cri LOGD
232 #endif
233 
234 #elif defined (MSOS_TYPE_OPTEE)
235 #define _msg(fmt, ...) printf(fmt, ##__VA_ARGS__)
236 #define _dbg(fmt, ...) printf(fmt, ##__VA_ARGS__)
237 #define _err(fmt, ...) printf(fmt, ##__VA_ARGS__)
238 #define _cri(fmt, ...) printf(fmt, ##__VA_ARGS__)
239 #else
_log(int lv,const char * fn,int ln,char * fmt,...)240 static void _log(int lv, const char *fn, int ln, char *fmt, ...) {
241     va_list ap;
242     char *tag[] = { "NA", "INFO", "DBG", "ERR", "WTF"};
243     int i;
244 
245     if(_u32CMDQDBGLevel==0) return;
246 
247     if(_u32CMDQDBGLevel > lv) return;
248 
249     i = (lv==4)?3:1;
250     va_start(ap, fmt);
251 
252     do {
253         ULOGE(TAG_DRV_CMDQ, "[cmdq][%s][%s:%d] ", tag[lv], fn, ln);
254         #ifdef MSOS_TYPE_LINUX_KERNEL
255         vprintk(fmt, ap);
256         #else
257         vprintf(fmt, ap);
258         #endif
259     } while(--i);
260 
261     va_end(ap);
262 }
263 
264 #define _msg(fmt, ...) //_log(1, __PRETTY_FUNCTION__, __LINE__, fmt, ##__VA_ARGS__)
265 #define _dbg(fmt, ...) _log(2, __PRETTY_FUNCTION__, __LINE__, fmt, ##__VA_ARGS__)
266 #define _err(fmt, ...) _log(3, __PRETTY_FUNCTION__, __LINE__, fmt, ##__VA_ARGS__)
267 #define _cri(fmt, ...) _log(4, __PRETTY_FUNCTION__, __LINE__, fmt, ##__VA_ARGS__)
268 #endif
269 
270 //--------------------------------------------------------------------------------------------------
271 //  Global Function
272 //--------------------------------------------------------------------------------------------------
273 //--------------------------------------------------------------------------------------------------
274 //  Backward compatibile API
275 //--------------------------------------------------------------------------------------------------
MDrv_CMDQ_Init(MS_U32 CMDQ_MIU_SELECT)276 DRVCMDQ_RESULT MDrv_CMDQ_Init(MS_U32 CMDQ_MIU_SELECT) {
277     return MDrv_CMDQv2_Init(0, CMDQ_MIU_SELECT);
278 }
MDrv_CMDQ_Start(MS_BOOL bStart)279 DRVCMDQ_RESULT MDrv_CMDQ_Start(MS_BOOL bStart) {
280     return MDrv_CMDQv2_Start(0, bStart);
281 }
MDrv_CMDQ_Get_Memory_Size(MS_PHY SmallAddr,MS_PHY BigAddr,MS_U32 miu_select)282 DRVCMDQ_RESULT MDrv_CMDQ_Get_Memory_Size(MS_PHY SmallAddr, MS_PHY BigAddr, MS_U32 miu_select) {
283     return MDrv_CMDQv2_Get_Memory_Size(0, SmallAddr, BigAddr, miu_select);
284 }
MDrv_CMDQ_Set_Buffer(MS_PHY StartAddr,MS_PHY EndAddr)285 DRVCMDQ_RESULT MDrv_CMDQ_Set_Buffer(MS_PHY StartAddr, MS_PHY EndAddr) {
286     return MDrv_CMDQv2_Set_Buffer(0, StartAddr, EndAddr);
287 }
MDrv_CMDQ_Reset(void)288 DRVCMDQ_RESULT MDrv_CMDQ_Reset(void) { return MDrv_CMDQv2_Reset(0); }
MDrv_CMDQ_Exit(void)289 DRVCMDQ_RESULT MDrv_CMDQ_Exit(void)  { return MDrv_CMDQv2_Exit(0);  }
MDrv_CMDQ_Stop(void)290 DRVCMDQ_RESULT MDrv_CMDQ_Stop(void)  { return MDrv_CMDQv2_Stop(0);  }
MDrv_CMDQ_Receive(CH_Struct_Pointer New_IP_Head)291 DRVCMDQ_RESULT MDrv_CMDQ_Receive(CH_Struct_Pointer New_IP_Head) {
292     return MDrv_CMDQv2_Receive(0, New_IP_Head);
293 }
Insert_Redundant_Null(MS_U32 Need_Null_Number)294 void Insert_Redundant_Null(MS_U32 Need_Null_Number) {
295     MDrv_CMDQv2_Insert_Redundant_Null(0, Need_Null_Number);
296 }
MDrv_CMDQ_Transfer(CAF_Struct_Pointer Array_Command,MS_SIZE Number_Array_Command)297 void MDrv_CMDQ_Transfer(CAF_Struct_Pointer Array_Command, MS_SIZE Number_Array_Command) {
298     MDrv_CMDQv2_Transfer(0, Array_Command, Number_Array_Command);
299 }
MDrv_CMDQ_Set_dummy_Address(MS_U32 DummyValue)300 void MDrv_CMDQ_Set_dummy_Address(MS_U32 DummyValue) {
301     MDrv_CMDQv2_Set_dummy_Address(0, DummyValue);
302 }
MDrv_CMDQ_Set_MIU_SELECT(MS_U32 miu_select)303 void MDrv_CMDQ_Set_MIU_SELECT(MS_U32 miu_select) {
304     MDrv_CMDQv2_Set_MIU_SELECT(0, miu_select);
305 }
MDrv_CMDQ_Set_timer_ratio(MS_U32 time,MS_U32 ratio)306 DRVCMDQ_RESULT MDrv_CMDQ_Set_timer_ratio(MS_U32 time,MS_U32 ratio) {
307     return MDrv_CMDQv2_Set_timer_ratio(0, time, ratio);
308 }
MDrv_CMDQ_Printf_Crash_Command(void)309 DRVCMDQ_RESULT MDrv_CMDQ_Printf_Crash_Command(void) {
310     return MDrv_CMDQv2_Printf_Crash_Command(0);
311 }
MDrv_CMDQ_Gen_WaitTrigger_Bus_Command(CAF_Struct_Pointer cmd,EN_CMDQTriggerBus_ID id,MS_BOOL falledge)312 void MDrv_CMDQ_Gen_WaitTrigger_Bus_Command(CAF_Struct_Pointer cmd, EN_CMDQTriggerBus_ID id, MS_BOOL falledge) {
313     MDrv_CMDQv2_Gen_WaitTrigger_Bus_Command(0, cmd, id, falledge);
314 }
MDrv_CMDQ_GetWritePoint(void)315 MS_U32 MDrv_CMDQ_GetWritePoint(void) {
316     return MDrv_CMDQv2_GetWritePoint(0);
317 }
MDrv_CMDQ_SetPowerState(EN_POWER_MODE u16PowerState)318 MS_U32 MDrv_CMDQ_SetPowerState(EN_POWER_MODE u16PowerState) {
319     return MDrv_CMDQv2_SetPowerState(0, u16PowerState);
320 }
MDrv_CMDQ_GetConfig(MS_PHY * SmallAddr,MS_PHY * BigAddr,MS_U32 * miu_select)321 MS_U32 MDrv_CMDQ_GetConfig(MS_PHY *SmallAddr, MS_PHY *BigAddr, MS_U32 *miu_select){
322     return MDrv_CMDQv2_GetConfig(0,SmallAddr,BigAddr,miu_select);
323 }
324 //--------------------------------------------------------------------------------------------------
325 //  Internal utility function
326 //--------------------------------------------------------------------------------------------------
IsHandleValid(int hnd)327 static inline DRVCMDQ_RESULT IsHandleValid(int hnd) {
328     if(hnd >= NUMBER_OF_CMDQ_HW || hnd < 0) {
329         _err("Invalid Handle %d.\n", hnd);
330         return DRVCMDQ_FAIL;
331     }
332     return DRVCMDQ_OK;
333 }
334 
InsertOneCommand(int hnd,MS_U32 a,MS_U32 b,MS_U32 c,MS_U32 d,MS_U32 e,MS_U32 f,MS_U32 g,MS_U32 h)335 static inline void InsertOneCommand(int hnd, MS_U32 a, MS_U32 b, MS_U32 c, MS_U32 d, MS_U32 e, MS_U32 f, MS_U32 g, MS_U32 h)
336 {
337     _msg(" cmdq(%d) cmd=0x%02X -> |L| %02x %02x %02x %02x %02x %02x %02x %02x |H|\n",
338          hnd, ((h&0xF0)>>4), a,b,c,d,e,f,g,h);
339 
340     _ctx[hnd].buffer_wrptr[0] = a;
341     _ctx[hnd].buffer_wrptr[1] = b;
342     _ctx[hnd].buffer_wrptr[2] = c;
343     _ctx[hnd].buffer_wrptr[3] = d;
344     _ctx[hnd].buffer_wrptr[4] = e;
345     _ctx[hnd].buffer_wrptr[5] = f;
346     _ctx[hnd].buffer_wrptr[6] = g;
347     _ctx[hnd].buffer_wrptr[7] = h;
348     _ctx[hnd].buffer_wrptr = _ctx[hnd].buffer_wrptr + 8;
349     _ctx[hnd].stats.cmd_count++;
350 }
351 
IssueCommand(int hnd,CAF_Struct_Pointer cmd)352 static DRVCMDQ_RESULT IssueCommand(int hnd, CAF_Struct_Pointer cmd) {
353     MS_U32 DDR_1 = 0, DDR_2 = 0, DDR_3 = 0, DDR_4 = 0, DDR_5 = 0, DDR_6 = 0, DDR_7 = 0, DDR_8 = 0;
354     MS_U32 u1 = 0, u2 = 0, u3 = 0;
355     MS_U32 mask_of_BF = 0x00ffffff;
356     MS_U32 bit_4 = 0xff;
357 
358     if(cmd == NULL) {
359         _err("illegal command pointer (NULL)\n");
360         return DRVCMDQ_INVALID_PARAM;
361     }
362 
363     _msg("Command: op: 0x%02x (%c) dest_addr: 0x%08x, dest_value: %04x, mask: %04x\n",
364          cmd->operation, cmd->operation, cmd->destionation_address, cmd->destionation_value, cmd->mask);
365 
366     switch(cmd->operation) {
367     case 'w':
368         // 0x77 is for write, using dat as input, usually used in FPGA/ASIC verification,
369         // the target_addr will be like 0xBF246BE0, write to "bank 0x123500, 8_bit F0"
370 
371         //RIU_addr << 1 | 0xBF000000 => destination_address.
372         u1 = (cmd->destionation_address & mask_of_BF) >> 2;
373         u2 = cmd->destionation_value;
374         u3 = cmd->mask;
375 
376         DDR_1 = 0x10;
377         DDR_2 = u1 >> 16;
378         DDR_3 = (u1 >> 8 & (bit_4));
379         DDR_4 = (u1) & (bit_4);
380         DDR_5 = u2 >> 8;         // write value, high bits
381         DDR_6 = u2 & (bit_4);    // write value, low  bits
382         DDR_7 = u3 >> 8;         // mask, high bits
383         DDR_8 = u3 & (bit_4);    // mask, low  bits
384         InsertOneCommand(hnd, DDR_8, DDR_7, DDR_6, DDR_5, DDR_4, DDR_3, DDR_2, DDR_1);
385         break;
386 
387     case 'W':
388         // 0x57 is for write, using cmdq_api to gen command, usually used in other drver code,
389         // the target_addr will be like 0x001235F0, write to "bank 0x123500, 8_bit F0"
390         u1 = cmd->destionation_address >> 1;
391         u2 = cmd->destionation_value;
392         u3 = cmd->mask;
393         DDR_1 = 0x10;                //command type
394         DDR_2 = u1 >> 16;            //target RIU
395         DDR_3 = (u1 >> 8 & (bit_4)); //target RIU
396         DDR_4 = (u1) & (bit_4);      //target RIU
397         DDR_5 = u2 >> 8;             //write value
398         DDR_6 = u2 & (bit_4);        //write value
399         DDR_7 = u3 >> 8;             //write mask
400         DDR_8 = u3 & (bit_4);        //write mask
401         InsertOneCommand(hnd, DDR_8, DDR_7, DDR_6, DDR_5, DDR_4, DDR_3, DDR_2, DDR_1);
402         break;
403 
404     case 'p':
405         // 0x70 is for polling_eq
406         _msg("\033[35mthis is polling equal command, which will finished with software interrupt: 0x1\033[m\n"); // joe.liu
407 
408         // RIU_addr << 1 | 0xBF000000 => destionation_address
409         u1 = (cmd->destionation_address & mask_of_BF) >> 1;
410         u2 = cmd->destionation_value;
411         u3 = cmd->mask;
412         DDR_1 = 0x31;                // add software interrupt: 1
413         DDR_2 = u1>>16;
414         DDR_3 = (u1 >> 8 & (bit_4));
415         DDR_4 = (u1) & (bit_4);
416         DDR_5 = u2 >> 8;
417         DDR_6 = u2 & (bit_4);
418         DDR_7 = u3 >> 8;
419         DDR_8 = u3 & (bit_4);
420         InsertOneCommand(hnd, DDR_8, DDR_7, DDR_6, DDR_5, DDR_4, DDR_3, DDR_2, DDR_1);
421         break;
422 
423     case 'C':
424         // 0x43 is for polling_neq
425         _dbg("\033[35mthis is polling non-equal command, which will finished with software interrupt: 0x2\033[m\n"); // joe.liu
426         // RIU_addr << 1 | 0xBF000000 => destionation_address
427         u1 = (cmd->destionation_address & mask_of_BF) >> 1;
428         u2 = cmd->destionation_value;
429         u3 = cmd->mask;
430         DDR_1 = 0xb2;                // add software interrupt: 2
431         DDR_2 = u1>>16;
432         DDR_3 = (u1 >> 8 & (bit_4));
433         DDR_4 = (u1) & (bit_4);
434         DDR_5 = u2 >> 8;
435         DDR_6 = u2 & (bit_4);
436         DDR_7 = u3 >> 8;
437         DDR_8 = u3 & (bit_4);
438         InsertOneCommand(hnd, DDR_8, DDR_7, DDR_6, DDR_5, DDR_4, DDR_3, DDR_2, DDR_1);
439         break;
440 
441     case 'F':
442         // 0x46 is for wait command for trigger_bus
443         _dbg("\033[35mthis is wait trigger bus signal command, which will finished with software interrupt: 0x4\033[m\n"); // joe.liu
444         DDR_1 = 0x24;    // add software interrupt: 4
445         DDR_2 = 0x00;
446         DDR_3 = 0x00;
447         DDR_4 = (cmd->destionation_address==0)?0x00:0x01;  // 0: detect rising, 1: detect falling
448         DDR_5 = 0x00;
449         DDR_6 = 0x00;
450         DDR_7 = cmd->mask >> 8;
451         DDR_8 = cmd->mask & (bit_4);
452         InsertOneCommand(hnd, DDR_8, DDR_7, DDR_6, DDR_5, DDR_4, DDR_3, DDR_2, DDR_1);
453         break;
454 
455     case 'N': //null command.
456         _msg("add null command\n");
457         InsertOneCommand(hnd, 0xFF, 0xFF, 0, 0, 0, 0, 0, 0);
458         break;
459 
460     default:
461         _err("Invalid command operation \"0x%0X\" issued.\n", cmd->operation);
462         return DRVCMDQ_INVALID_PARAM;
463         break;
464     }
465     return DRVCMDQ_OK;
466 }
467 
468 //---------------------------------------------------------------------------------------------------------------------
469 ///Get MMIO_Base and set struct _REG_CMDQCtrl * _CMDQCtrl
470 ///Remember the caller need to do "MsOS_MPool_Mapping()" and "MDrv_CMDQ_Get_Memory_Size()" for setting the buffer!!
471 //---------------------------------------------------------------------------------------------------------------------
MDrv_CMDQv2_Init(int hnd,MS_U32 CMDQ_MIU_SELECT)472 DRVCMDQ_RESULT MDrv_CMDQv2_Init(int hnd, MS_U32 CMDQ_MIU_SELECT)
473 {
474     MS_VIRT u32Bank = 0x0;
475     MS_VIRT u32shmAddr;
476     MS_PHY u32BankSize = 0x0;
477     MS_U32 u32Ret, u32ShmId, u32shmBufSize;
478 
479     if(IsHandleValid(hnd) != DRVCMDQ_OK)
480         return DRVCMDQ_FAIL;
481 
482     if(CMDQ_MIU_SELECT >= MIU_NOT_SUPPORT)
483     {
484         _err("\033[35mCMDQ_MIU_SELECT is %d, we only support MIU0 or MIU1\033[m\n", CMDQ_MIU_SELECT);
485         return DRVCMDQ_FAIL;
486     }
487 
488     if(FALSE == MDrv_MMIO_GetBASE(&u32Bank, &u32BankSize, MS_MODULE_CMDQ))
489     {
490         _err("\033[35mu32Bank is 0x%X and u32BankSize is 0x%X\033[m\n", (unsigned int)u32Bank, (unsigned int)u32BankSize);
491         return DRVCMDQ_FAIL;
492     }
493 
494     CMDQ_MUTEX_CREATE(hnd);
495     CMDQ_MUTEX_LOCK(hnd);
496     HAL_CMDQ_SetBank(hnd, u32Bank); // not sure if this HAL_CMDQ_SetBank() need to be done for every process if STR
497 
498     /* get a str_flag */
499     u32Ret = MsOS_SHM_GetId((MS_U8*)"cmdq_str_flag", sizeof(MS_U32), &u32ShmId, &u32shmAddr, &u32shmBufSize, MSOS_SHM_QUERY);
500     if(u32Ret == TRUE)
501     {
502         IS_STR_RESUME = *(MS_U32*)u32shmAddr;
503     }
504 
505     //below, if we check shm and return ok, but we still keep miu_select info in our context.
506     _ctx[hnd].CMDQ_BUFFER_MIU = CMDQ_MIU_SELECT;
507 
508     /* use SHM to check if inited, if one process already inited it, other processes do not need to init */
509     u32Ret = MsOS_SHM_GetId((MS_U8*)_ctx[hnd].shm_name, sizeof(ShmCtx), &u32ShmId, (MS_VIRT*)&_ctx[hnd].shm, &u32shmBufSize, MSOS_SHM_QUERY);
510     if( (u32Ret == TRUE) && (IS_STR_RESUME == 0) )
511     {
512         _dbg("\033[35mCMDQ already inited, and IS_STR_RESUME is %d\033[m\n", IS_STR_RESUME);
513         CMDQ_MUTEX_UNLOCK(hnd);
514         return DRVCMDQ_OK;
515     }
516 
517     /* following is default setiing, we need to modify the "mapping region" and "start/end region" according to CMDQ_BUFFER_MIU
518      * if you set cmdq buffer at MIU_1, you must set the "cmdq miu_sel bit" to be 1, we only support MIU_0 or MIU_1
519      * the MDrv_CMDQ_Get_Memory_Size() will set the "start/end address of cmdq buffer",
520      * for simplifying, we all use phy_addr instead of miu_offset to specify "start/end address of cmdq buffer" in RIU
521      * however, the para passed into MDrv_CMDQ_Get_Memory_Size() should be miu_offset, we will convert it to phy_addr in MDrv_CMDQ_Get_Memory_Size()
522      * IMPORTANT: CMDQ does not support MIU2/3!!
523      */
524     if(_ctx[hnd].CMDQ_BUFFER_MIU)
525     {
526         // set select_MIU to MIU_1
527         MDrv_CMDQv2_Set_MIU_SELECT(hnd, _ctx[hnd].CMDQ_BUFFER_MIU);
528     }
529     else
530     {
531         // set select_MIU to MIU_0
532         MDrv_CMDQv2_Set_MIU_SELECT(hnd, _ctx[hnd].CMDQ_BUFFER_MIU);
533     }
534 
535     HAL_CMDQ_Enable(hnd);
536     HAL_CMDQ_Reset(hnd);
537 
538     if(FALSE == HAL_CMDQ_Set_Mode(hnd, _ctx[hnd].CMDQ_MODE))
539     {
540         _err("\033[35mCMDQ Set Mode FAIL!!\033[m\n");
541         CMDQ_MUTEX_UNLOCK(hnd);
542         return DRVCMDQ_FAIL;
543     }
544 
545     /* the polling_timer is for re-checking polling value, if the time_interval is too small, cmdq will polling RIU frequently, so that RIU will very busy */
546     MDrv_CMDQv2_Set_timer_ratio(hnd, 0x000000FF, 0x0000000F);        // set time / ratio, total wait time is (wait_time * (ratio + 1)) => ( FF * (F + 1) / 216MHz ) = sec
547 
548     // create a shm for cmdq str init
549     if(FALSE == MsOS_SHM_GetId((MS_U8*)"cmdq_str_flag", sizeof(MS_U32), &u32ShmId, &u32shmAddr, &u32shmBufSize, MSOS_SHM_CREATE))
550     {
551         _cri("[cmdq get shm error] something wrong in MsOS_SHM_GetId\n");
552         _cri("is SHM_SIZE reached?\n");
553         _cri("is MAX_SHM_CLIENT_NUM reached?\n");
554         CMDQ_MUTEX_UNLOCK(hnd);
555         return DRVCMDQ_FAIL;
556     }
557 
558     if(FALSE == MsOS_SHM_GetId((MS_U8*)_ctx[hnd].shm_name, sizeof(ShmCtx), &u32ShmId, (MS_VIRT*)&_ctx[hnd].shm, &u32shmBufSize, MSOS_SHM_CREATE))
559     {
560         _cri(" FAIL TO CREATE SHM(%s). with size %d.\n", _ctx[hnd].shm_name, sizeof(ShmCtx));
561         _cri("is SHM_SIZE reached?\n");
562         _cri("is MAX_SHM_CLIENT_NUM reached?\n");
563         CMDQ_MUTEX_UNLOCK(hnd);
564         return DRVCMDQ_FAIL;
565     }
566 
567 	if(_ctx[hnd].shm->init == 0)	/* only first init will assign shm data, and not form STR_RESUME */
568 	{
569 		_ctx[hnd].shm->init = 1;
570     	_ctx[hnd].shm->miu_select = _ctx[hnd].CMDQ_BUFFER_MIU;
571     	_ctx[hnd].shm->buffer_wr = 0; //following code flow check 0 to know its not setup.
572 	}
573 
574 	_msg("set _ctx[%d].shm->buffer_wr to 0x%X\n", hnd, _ctx[hnd].shm->buffer_wr);
575 	_dbg("set _ctx[%d].shm->buffer_wr to 0x%X\n", hnd, _ctx[hnd].shm->buffer_wr);
576 	_err("set _ctx[%d].shm->buffer_wr to 0x%X\n", hnd, _ctx[hnd].shm->buffer_wr);
577 	_cri("set _ctx[%d].shm->buffer_wr to 0x%X\n", hnd, _ctx[hnd].shm->buffer_wr);
578 
579 	_msg("IS_STR_RESUME is %d\n", IS_STR_RESUME);
580 	_dbg("IS_STR_RESUME is %d\n", IS_STR_RESUME);
581 	_err("IS_STR_RESUME is %d\n", IS_STR_RESUME);
582 	_cri("IS_STR_RESUME is %d\n", IS_STR_RESUME);
583 
584     CMDQ_MUTEX_UNLOCK(hnd);
585     return DRVCMDQ_OK;
586 }
587 
MDrv_CMDQ_GetLibVer(const MSIF_Version ** ppVersion)588 DRVCMDQ_RESULT MDrv_CMDQ_GetLibVer(const MSIF_Version **ppVersion)
589 {
590     // No mutex check, it can be called before Init
591     if (!ppVersion)
592     {
593         return DRVCMDQ_FAIL;
594     }
595 
596     *ppVersion = &_drv_comq_version;
597     return DRVCMDQ_OK;
598 }
599 
600 //--------------------------------------------------------------------------------------------------
601 // In ring-buffer mode, this function will trig for update reg_sw_wr_mi_wadr
602 // The CMDQ will keep on executing cmd until reg_rd_mi_radr reach reg_sw_wr_mi_wadr
603 //--------------------------------------------------------------------------------------------------
MDrv_CMDQv2_Start(int hnd,MS_BOOL bStart)604 DRVCMDQ_RESULT MDrv_CMDQv2_Start(int hnd, MS_BOOL bStart)
605 {
606     if(IsHandleValid(hnd) != DRVCMDQ_OK)
607         return DRVCMDQ_INVALID_PARAM;
608 
609     if(bStart == 1)
610     {
611         _msg("trigger cmdq to start!\n");
612         HAL_CMDQ_Start(hnd);
613         return DRVCMDQ_OK;
614     }
615     else
616     {
617         _msg("bStart %d \n",bStart);
618         return DRVCMDQ_FAIL;
619     }
620 }
621 
622 //--------------------------------------------------------------------------------------------------
623 // Set the Start and End address of CMDQ DRAM(use miu_offset and miu_select to get phy_addr)
624 // @ \b in: SmallAddr => Start address     (miu_offset)
625 // @ \b in: BigAddr   => End address    (miu_offset)
626 //--------------------------------------------------------------------------------------------------
627 // this function should be called for setting CMDQ Buffer(System Side), need to add in ioctl for utopia2
MDrv_CMDQv2_Get_Memory_Size(int hnd,MS_PHY SmallAddr,MS_PHY BigAddr,MS_U32 miu_select)628 DRVCMDQ_RESULT MDrv_CMDQv2_Get_Memory_Size(int hnd, MS_PHY SmallAddr, MS_PHY BigAddr, MS_U32 miu_select)
629 {
630     MS_PHY pa_start = 0;
631     MS_VIRT u32shmAddr;
632     MS_VIRT va_SmallAddr = 0, va_BigAddr = 0;
633     MS_U32 u32Ret, u32ShmId, u32shmBufSize;
634     MS_PHY CMDQ_BUFFER_START = SmallAddr;
635     MS_PHY CMDQ_BUFFER_END = BigAddr;
636 
637     if(IsHandleValid(hnd) != DRVCMDQ_OK)
638         return DRVCMDQ_FAIL;
639 
640     if(miu_select >= MIU_NOT_SUPPORT)
641     {
642         _err("\033[35mmiu_select is %d, we only support MIU0 or MIU1\033[m\n", miu_select);
643         return DRVCMDQ_FAIL;
644     }
645 
646         BigAddr -= 16;    // cause the ori BigAddr is other IP buffer head, we need to decrease one bus line
647 
648     _miu_offset_to_phy(miu_select,0,pa_start);
649     /* get the start/end va_addr, remember the caller should do mmaping first */
650     va_SmallAddr    = MS_PA2KSEG1(SmallAddr + pa_start);
651     va_BigAddr      = MS_PA2KSEG1(BigAddr + pa_start);
652 
653     if( (va_SmallAddr == 0x0UL) || (va_BigAddr == 0x0UL) )
654     {
655         _cri("is the region from SmallAddr to BigAddr mmaped?\n");
656         return DRVCMDQ_FAIL;
657     }
658 
659     /* caller can pass miu_offset directly, and we will help to change to cmdq_used(only see command line, each line having 16-byte, two commands) */
660     SmallAddr    = SmallAddr >> BUS_SHIFT;
661     BigAddr      = BigAddr   >> BUS_SHIFT;
662     pa_start     = pa_start  >> BUS_SHIFT;
663 
664     CMDQ_MUTEX_LOCK(hnd);
665 
666     /* get a str_flag */
667     u32Ret = MsOS_SHM_GetId((MS_U8*)"cmdq_str_flag", sizeof(MS_U32), &u32ShmId, &u32shmAddr, &u32shmBufSize, MSOS_SHM_QUERY);
668     if(u32Ret == TRUE)
669     {
670         _msg("succeed to get STR flag from shared memory.\n");
671         IS_STR_RESUME = *(MS_U32*)u32shmAddr;
672     }
673 	_msg("IS_STR_RESUME is %d\n", IS_STR_RESUME);
674 	_dbg("IS_STR_RESUME is %d\n", IS_STR_RESUME);
675 	_err("IS_STR_RESUME is %d\n", IS_STR_RESUME);
676 	_cri("IS_STR_RESUME is %d\n", IS_STR_RESUME);
677 
678     /* use SHM to check if inited, if one process already inited it, other processes do not need to init */
679     u32Ret = MsOS_SHM_GetId((MS_U8*)_ctx[hnd].shm_name, sizeof(ShmCtx), &u32ShmId, (MS_VIRT*)&_ctx[hnd].shm, &u32shmBufSize, MSOS_SHM_QUERY);
680     if( u32Ret == FALSE )
681     {
682         _cri("[cmdq get shm error] something wrong in MsOS_SHM_GetId\n");
683         _cri("is SHM_SIZE reached?\n");
684         _cri("is MAX_SHM_CLIENT_NUM reached?\n");
685         _cri("its very weird die here. after CMDQ_Init(), shm should be query-able!!\n");
686         return DRVCMDQ_FAIL;
687     }
688     _msg("succeed to get shared memory of handle %d\n", hnd);
689 
690     if( (IS_STR_RESUME == 0) && (_ctx[hnd].shm->buffer_wr != 0) )
691     {
692         _dbg("\033[35mget Memory_Start_Address from shm\033[m\n");
693         // get from SHM, to prevent multi-process using different wr_adr
694         _ctx[hnd].buffer_wr      = _ctx[hnd].shm->buffer_wr;
695         _ctx[hnd].buffer_start   = SmallAddr + pa_start; // fix to be buffer_start
696         _ctx[hnd].buffer_end     = BigAddr   + pa_start; // fix to be buffer_end
697     }
698     else
699     {
700         if(IS_STR_RESUME == 1)
701         {
702             _ctx[hnd].buffer_wr  = _ctx[hnd].shm->buffer_wr;
703             _msg("still _ctx[%d].shm->buffer_wr to 0x%lX\n", hnd, _ctx[hnd].shm->buffer_wr);
704             _dbg("still _ctx[%d].shm->buffer_wr to 0x%lX\n", hnd, _ctx[hnd].shm->buffer_wr);
705             _err("still _ctx[%d].shm->buffer_wr to 0x%lX\n", hnd, _ctx[hnd].shm->buffer_wr);
706             _cri("still _ctx[%d].shm->buffer_wr to 0x%lX\n", hnd, _ctx[hnd].shm->buffer_wr);
707         }
708         else //first time to setup buffer_wr.
709         {
710             _ctx[hnd].buffer_wr      = SmallAddr + pa_start;
711             _ctx[hnd].shm->buffer_wr = _ctx[hnd].buffer_wr;
712             _msg("[1] update _ctx[%d].shm->buffer_wr to 0x%lX\n", hnd, _ctx[hnd].shm->buffer_wr);
713             _dbg("[1] update _ctx[%d].shm->buffer_wr to 0x%lX\n", hnd, _ctx[hnd].shm->buffer_wr);
714             _err("[1] update _ctx[%d].shm->buffer_wr to 0x%lX\n", hnd, _ctx[hnd].shm->buffer_wr);
715             _cri("[1] update _ctx[%d].shm->buffer_wr to 0x%lX\n", hnd, _ctx[hnd].shm->buffer_wr);
716         }
717 
718         _ctx[hnd].buffer_start   = SmallAddr + pa_start; // fix to be buffer_start
719         _ctx[hnd].buffer_end     = BigAddr   + pa_start; // fix to be buffer_end
720         MDrv_CMDQv2_Set_Buffer(hnd, _ctx[hnd].buffer_start, _ctx[hnd].buffer_end);
721     }
722     // Number of Command Line
723     _ctx[hnd].TOTAL_BUFFER_SIZE = ( (va_BigAddr >> 4) - (va_SmallAddr >> 4) + 1 );
724 
725     /* save a str_flag(reset to 0) */
726     *(MS_U32*)u32shmAddr = 0;
727     _ctx[hnd].shm->miu_select = miu_select;
728     _ctx[hnd].shm->buffer_start = CMDQ_BUFFER_START;
729     _ctx[hnd].shm->buffer_end   = CMDQ_BUFFER_END;
730 
731     CMDQ_MUTEX_UNLOCK(hnd);
732     _msg("DONE.\n");
733     return DRVCMDQ_OK;
734 }
735 
MDrv_CMDQv2_Set_Buffer(int hnd,MS_PHY StartAddr,MS_PHY EndAddr)736 DRVCMDQ_RESULT MDrv_CMDQv2_Set_Buffer(int hnd, MS_PHY StartAddr, MS_PHY EndAddr)
737 {
738     if(IsHandleValid(hnd) != DRVCMDQ_OK)
739         return DRVCMDQ_FAIL;
740 
741     HAL_CMDQ_Set_Start_Pointer(hnd, StartAddr);
742     HAL_CMDQ_Set_End_Pointer(hnd, EndAddr);
743     _msg("set cmd%d buffer from %llu to %llu\n", hnd, StartAddr, EndAddr);
744     return DRVCMDQ_OK;
745 }
746 
747 // currently not used
MDrv_CMDQv2_Reset(int hnd)748 DRVCMDQ_RESULT MDrv_CMDQv2_Reset(int hnd)
749 {
750     if(IsHandleValid(hnd) != DRVCMDQ_OK)
751         return DRVCMDQ_FAIL;
752 
753     CMDQ_MUTEX_LOCK(hnd);
754     HAL_CMDQ_Reset(hnd);
755     CMDQ_MUTEX_UNLOCK(hnd);
756     return DRVCMDQ_OK;
757 }
758 
MDrv_CMDQv2_Exit(int hnd)759 DRVCMDQ_RESULT MDrv_CMDQv2_Exit(int hnd)
760 {
761     if(IsHandleValid(hnd) != DRVCMDQ_OK)
762         return DRVCMDQ_FAIL;
763 
764     CMDQ_MUTEX_LOCK(hnd);
765     MDrv_CMDQv2_Set_dummy_Address(hnd, 0x5566);
766     HAL_CMDQ_Stop(hnd);
767     CMDQ_MUTEX_UNLOCK(hnd);
768     CMDQ_MUTEX_DELETE(hnd);
769     return DRVCMDQ_OK;
770 }
771 
MDrv_CMDQv2_Stop(int hnd)772 DRVCMDQ_RESULT MDrv_CMDQv2_Stop(int hnd)
773 {
774     MS_U32 size;
775 
776     if(IsHandleValid(hnd) != DRVCMDQ_OK)
777         return DRVCMDQ_FAIL;
778 
779     CMDQ_MUTEX_LOCK(hnd);
780     //reset
781     _msg("SW RST pull low\n");
782     HAL_CMDQ_Reset2(hnd, 0); //low
783 
784     //clear buffer
785     _msg("clear buffer\n");
786     size = _ctx[hnd].TOTAL_BUFFER_SIZE << 4;
787     memset((void*)MS_PA2KSEG1((MS_PHY)_ctx[hnd].buffer_start<<4), 0, size);
788     MsOS_Dcache_Flush(MS_PA2KSEG1((MS_PHY)_ctx[hnd].buffer_start << 4), size-1);
789     MsOS_FlushMemory();
790 
791     _msg("reset wr pointer\n");
792     //update write pointer.
793     _ctx[hnd].buffer_wr = _ctx[hnd].shm->buffer_wr = _ctx[hnd].buffer_start;
794 
795     _msg("[2] update _ctx[%d].shm->buffer_wr to 0x%lX\n", hnd, _ctx[hnd].shm->buffer_wr);
796     _dbg("[2] update _ctx[%d].shm->buffer_wr to 0x%lX\n", hnd, _ctx[hnd].shm->buffer_wr);
797     _err("[2] update _ctx[%d].shm->buffer_wr to 0x%lX\n", hnd, _ctx[hnd].shm->buffer_wr);
798     _cri("[2] update _ctx[%d].shm->buffer_wr to 0x%lX\n", hnd, _ctx[hnd].shm->buffer_wr);
799     HAL_CMDQ_Write_Pointer(hnd, _ctx[hnd].buffer_wr);
800 
801     _msg("SW RST pull high\n");
802     HAL_CMDQ_Reset2(hnd, 1); //high
803 
804     _dbg("We DO stop and flush buffer when Stop() called. now\n");
805     MDrv_CMDQv2_Set_dummy_Address(hnd, 0x7878);
806 
807     CMDQ_MUTEX_UNLOCK(hnd);
808     return DRVCMDQ_OK;
809 }
810 
MDrv_CMDQ_SetDbgLevel(DrvCMDQ_DbgLevel DbgLevel)811 DRVCMDQ_RESULT MDrv_CMDQ_SetDbgLevel(DrvCMDQ_DbgLevel DbgLevel)
812 {
813     _u32CMDQDBGLevel = 1; //make following _dbg() always show.
814     _dbg("setup debug level => %lu\n", DbgLevel);
815     _u32CMDQDBGLevel = DbgLevel;
816     return DRVCMDQ_OK;
817 }
818 
MDrv_CMDQv2_Receive(int hnd,CH_Struct_Pointer New_IP_Head)819 DRVCMDQ_RESULT MDrv_CMDQv2_Receive(int hnd, CH_Struct_Pointer New_IP_Head)
820 {
821     MS_SIZE New_CommandArray_Number = 0;        // Command_Line Number in DRAM
822     MS_SIZE Transfer_Number = 0;                // Command Number
823     MS_U32  avail;
824 
825     if(IsHandleValid(hnd) != DRVCMDQ_OK)
826         return DRVCMDQ_FAIL;
827 
828     CMDQ_MUTEX_LOCK(hnd);
829     CAF_Struct_Pointer New_CommandArray_Pointer = New_IP_Head->Pointer_To_CAFArray;
830     Transfer_Number = New_IP_Head->Command_Number;
831     New_CommandArray_Number = New_IP_Head->Command_Number;
832 
833     if(New_CommandArray_Number & 0x0000001UL)  // new receive struct odd or even
834     {
835         New_CommandArray_Number = (New_CommandArray_Number+1) / 2;
836     }
837     else
838     {
839         New_CommandArray_Number = New_CommandArray_Number/2;
840     }
841 
842     if(New_CommandArray_Number > _ctx[hnd].TOTAL_BUFFER_SIZE-1)
843     {
844         _err("request command size %lu is larger than total command size %lu\n",
845              New_CommandArray_Number, _ctx[hnd].TOTAL_BUFFER_SIZE-1);
846         CMDQ_MUTEX_UNLOCK(hnd);
847         return DRVCMDQ_FAIL;
848     }
849 
850     // get from SHM, to prevent multi-process using different wr_adr
851     _ctx[hnd].buffer_wr = _ctx[hnd].shm->buffer_wr;
852 
853     avail = MDrv_CMDQv2_Get_FreeCmdLine_Size(hnd);
854     if(avail < New_CommandArray_Number)
855     {
856         _err("not enough free space for %d command(128bit). available = %d\n",
857              New_CommandArray_Number, avail);
858         CMDQ_MUTEX_UNLOCK(hnd);
859         return DRVCMDQ_FAIL;
860     }
861 
862     _msg("Memory_Start_Address %llu\n", (unsigned long long)_ctx[hnd].buffer_wr);
863     _msg("New_CommandArray_Number %llu\n", (unsigned long long)New_CommandArray_Number);
864 
865     //to get a VA by using PA, Remember to use MsOS_Mapping to get CMDQ_Buffer Mapping
866     _ctx[hnd].buffer_wrptr = (MS_U8*)MS_PA2KSEG1((MS_PHY)_ctx[hnd].buffer_wr << 4);
867     _msg("buffer_wrptr start from 0x%llx\n", (unsigned long)_ctx[hnd].buffer_wrptr);
868 
869     // step_1: Write CMD to CMDQ Buffer
870     MDrv_CMDQv2_Transfer(hnd, New_CommandArray_Pointer, Transfer_Number);
871     //we do flush in _Transfer(), because might be one or two segment of memory.
872 
873     // if buffer_wr == buffer_start
874     //   step_2: Update software write position of command in miu
875     //   (Need to take care of if using ring buffer, which will occurs when New_CommandArray_Number = TOTAL_BUFFER_SIZE)
876     // else
877     //   step_2: Update software write position of command in miu (Need to take care of if using ring buffer)
878 
879     // will do unsign_ext for New_CommandArray_Number first
880     _ctx[hnd].buffer_wr += New_CommandArray_Number;
881 
882     if(_ctx[hnd].buffer_wr > _ctx[hnd].buffer_end)
883     {
884         // actually, in this case, New_CommandArray_Number will large/equal to TOTAL_BUFFER_SIZE,
885         // this case should return DRVCMDQ_FAIL at upper check
886         _msg("Adjust Memory_Start_Address FROM 0x%016llx\n",
887              (unsigned long long)_ctx[hnd].buffer_wr);
888         _ctx[hnd].buffer_wr =
889             _ctx[hnd].buffer_wr -
890             _ctx[hnd].buffer_end - 1 +
891             _ctx[hnd].buffer_start;
892         _msg("                            TO   0x%016llx\n",
893              (unsigned long long)_ctx[hnd].buffer_wr);
894     }
895 
896     // step_3: update buffer_wr to shm
897     _ctx[hnd].shm->buffer_wr = (MS_VIRT)_ctx[hnd].buffer_wr;
898 	//_msg("[cmdq_fire] update _ctx[%d].shm->buffer_wr to 0x%lX\n", hnd, _ctx[hnd].shm->buffer_wr);
899 	//_dbg("[cmdq_fire] update _ctx[%d].shm->buffer_wr to 0x%lX\n", hnd, _ctx[hnd].shm->buffer_wr);
900 	//_err("[cmdq_fire] update _ctx[%d].shm->buffer_wr to 0x%lX\n", hnd, _ctx[hnd].shm->buffer_wr);
901 	//_cri("[cmdq_fire] update _ctx[%d].shm->buffer_wr to 0x%lX\n", hnd, _ctx[hnd].shm->buffer_wr);
902     /*
903      * update wr_adr to let cmdq know the stop_execution addr(wr_adr),
904      * when read_addr = wr_adr, stop read and execute what have read
905      * so, after trigger, the cmdq will execute until reach wr_adr
906      */
907     HAL_CMDQ_Write_Pointer(hnd, _ctx[hnd].buffer_wr);
908 
909     // step_4: trigger to start
910     MDrv_CMDQv2_Start(hnd, 1);
911 
912     _ctx[hnd].stats.cmd_setcount++;
913     CMDQ_MUTEX_UNLOCK(hnd);
914     return DRVCMDQ_OK;
915 }
916 
MDrv_CMDQv2_Insert_Redundant_Null(int hnd,MS_U32 Need_Null_Number)917 void MDrv_CMDQv2_Insert_Redundant_Null(int hnd, MS_U32 Need_Null_Number)
918 {
919     MS_U32 j = 0;
920     Need_Null_Number *= 2;
921 
922     if(IsHandleValid(hnd) != DRVCMDQ_OK)
923     {
924         _cri("Invalid handle plz. %d\n", hnd);
925         MS_ASSERT(0);
926     }
927 
928     for(j = 0; j < Need_Null_Number; j++)
929     {
930         //@FIXME, here, we might exceed end of buffer address.!!!
931         _msg("Insert #%d Null_Commands\n", j);
932         InsertOneCommand(hnd, 0,0,0,0,0,0,0,0);
933     }
934 }
935 
936 //--------------------------------------------------------------------------------------------------
937 // Write the CAF content to CMDQ Buffer
938 // @ \b in: Array_Command => Pointer to CAF
939 // @ \b in: Number_Array_Command => Number of Commands
940 //--------------------------------------------------------------------------------------------------
MDrv_CMDQv2_Transfer(int hnd,CAF_Struct_Pointer Array_Command,MS_SIZE Number_Array_Command)941 void MDrv_CMDQv2_Transfer(int hnd, CAF_Struct_Pointer Array_Command, MS_SIZE Number_Array_Command)
942 {
943     MS_U32 i = 0;
944     DRVCMDQ_RESULT ret;
945     MS_U8 topad;
946     MS_U8 twoflush = 0;
947     MS_SIZE a,b;
948     MS_U8 *endptr;
949 
950     if(IsHandleValid(hnd) != DRVCMDQ_OK)
951     {
952         _cri("Invalid handle plz. %d\n", hnd);
953         MS_ASSERT(0);
954     }
955 
956     topad = (Number_Array_Command & 0x1UL)?1:0;
957 
958     //@NOTE: we use VA to compare with wrptr, because VA2PA(wrptr)
959     // that wrptr might exceed buffer address, which address is not mmio-ed.
960     endptr = (MS_U8*)MS_PA2KSEG1((MS_PHY)_ctx[hnd].buffer_end << 4);
961     endptr += 16;
962 
963     for(i = 0; i < (Number_Array_Command + topad); i++)
964     {
965         /* RING BUFFER CONDITION
966            |S|______R.........W______|E| when W exceed |E|, need to be handled.
967 
968            |S|......W_________R......|E| when W exceed R  , need to be handled.
969            BUT, we handle this in Receive() func. it never happen here.
970          */
971 
972         // This Command is over buffer_end, change to Buffer Head
973         // However, the buffer_end can insert CMD
974         if(_ctx[hnd].buffer_wrptr >= endptr)
975         {
976             _msg("@%d/%d cmds\n", i, Number_Array_Command);
977             _msg("Restart Ring buffer: buffer_end is  0x%016llx\n",
978                  endptr);
979             _msg("          Current Write Address is  0x%016llx\n",
980                  _ctx[hnd].buffer_wrptr);
981             _msg("Change buffer_wrptr to Buffer Head: 0x%016llx\n",
982                  (MS_U32)MS_PA2KSEG1((MS_PHY)_ctx[hnd].buffer_start << 4));
983 
984             _ctx[hnd].buffer_wrptr = (MS_U8*)MS_PA2KSEG1((MS_PHY)_ctx[hnd].buffer_start << 4);
985             twoflush = 1;
986         }
987 
988         if(topad && (i==Number_Array_Command)) {
989             _ctx[hnd].stats.cmd_nullcnt++;
990 #if 1
991             InsertOneCommand(hnd, 0xFF,0xFF,0,0,0,0,0,0);
992 #else
993             // test if CMDQ works
994             InsertOneCommand(hnd, 0x00, 0x00, 0x34, 0x12, 0xF8, 0x1A, 0x09, 0x10);
995 #endif
996             _dbg("\033[35mOdd instructions\033[m\n");
997         }
998         else
999         {
1000             _msg("%d issue %p\n", i, _ctx[hnd].buffer_wrptr);
1001             ret = IssueCommand(hnd, &Array_Command[i]);
1002             if(ret != DRVCMDQ_OK)
1003             {
1004                 _err("\033[35mError, Unknown opertion!! Array_Command[%d].operation is %u\033[m\n", i, Array_Command[i].operation);
1005             }
1006         }
1007     }
1008 
1009     if(twoflush)
1010     {
1011         // |S|__b____R.........W___a___|E|
1012         a = (_ctx[hnd].buffer_end-_ctx[hnd].buffer_wr+1)<<4;
1013         //flush from wr to end
1014         //@FIXME: this is very weird implementation of Dcache_Flush.
1015         //that we need to -1, in case it internally do touch address of (ptr+size).
1016         //if the second parameter is size.....
1017         MsOS_Dcache_Flush(MS_PA2KSEG1((MS_PHY)_ctx[hnd].buffer_wr<<4), a-1);
1018         MsOS_FlushMemory();
1019         _msg("Flush seg #a from 0x%016llx with %lu bytes\n", _ctx[hnd].buffer_wr<<4, a);
1020         //flush from start to data end.
1021         b = ((Number_Array_Command+(topad?1:0)) << 3) - a;
1022         if(b!=0)
1023         {
1024             MsOS_Dcache_Flush(MS_PA2KSEG1((MS_PHY)_ctx[hnd].buffer_start<<4), b);
1025             MsOS_FlushMemory();
1026             _msg("Flush seg #b from 0x%016llx with %lu bytes\n", _ctx[hnd].buffer_start<<4, b);
1027         }
1028     }
1029     else
1030     {
1031         a = ((Number_Array_Command+(topad?1:0)) << 3);
1032         //@FIXME: this is very werid implementation of Dcache_Flush.
1033         //that we need to -1, in case wr+a is end of buffer,
1034         //that cause VA2PA fail internally in Flush() which misunderstanding msg show.
1035         MsOS_Dcache_Flush(MS_PA2KSEG1((MS_PHY)_ctx[hnd].buffer_wr<<4), a-1);
1036         MsOS_FlushMemory();  //flush OCP data
1037         _msg("Flush from 0x%016llx with %d bytes\n", (_ctx[hnd].buffer_wr<<4), a);
1038     }
1039 }
1040 
MDrv_CMDQv2_Set_dummy_Address(int hnd,MS_U32 DummyValue)1041 void MDrv_CMDQv2_Set_dummy_Address(int hnd, MS_U32 DummyValue)
1042 {
1043     if(IsHandleValid(hnd) != DRVCMDQ_OK)
1044     {
1045         _cri("Invalid handle plz. %d\n", hnd);
1046         MS_ASSERT(0);
1047     }
1048 
1049     HAL_CMDQ_Write_Dummy_Register(hnd, DummyValue);
1050 }
1051 
MDrv_CMDQv2_Set_MIU_SELECT(int hnd,MS_U32 miu_select)1052 void MDrv_CMDQv2_Set_MIU_SELECT(int hnd, MS_U32 miu_select)
1053 {
1054     if(IsHandleValid(hnd) != DRVCMDQ_OK)
1055     {
1056         _cri("Invalid handle plz. %d\n", hnd);
1057         MS_ASSERT(0);
1058     }
1059 
1060     _dbg("CMDQ(%d) MIU set to %lu\n", hnd, miu_select);
1061     HAL_CMDQ_Set_MIU_SELECT(hnd, miu_select);
1062 }
1063 
MDrv_CMDQv2_Set_timer_ratio(int hnd,MS_U32 time,MS_U32 ratio)1064 DRVCMDQ_RESULT MDrv_CMDQv2_Set_timer_ratio(int hnd, MS_U32 time, MS_U32 ratio)
1065 {
1066     if(IsHandleValid(hnd) != DRVCMDQ_OK)
1067         return DRVCMDQ_FAIL;
1068 
1069     HAL_CMDQ_Set_Timer(hnd, time);
1070     HAL_CMDQ_Set_Ratio(hnd, ratio);
1071     return DRVCMDQ_OK;
1072 }
1073 
MDrv_CMDQv2_Printf_Crash_Command(int hnd)1074 DRVCMDQ_RESULT MDrv_CMDQv2_Printf_Crash_Command(int hnd)
1075 {
1076     MS_U32 Command_15_0_bit, Command_31_16_bit, Command_55_32_bit, Command_63_56_bit;
1077 
1078     if(IsHandleValid(hnd) != DRVCMDQ_OK)
1079         return DRVCMDQ_FAIL;
1080 
1081     /* see low 16-bit */
1082     Command_15_0_bit = HAL_CMDQ_Error_Command(hnd, CMDQ_CRASH_15_0_BIT);
1083     Command_31_16_bit = HAL_CMDQ_Error_Command(hnd, CMDQ_CRASH_31_16_BIT);
1084     Command_55_32_bit = HAL_CMDQ_Error_Command(hnd, CMDQ_CRASH_55_32_BIT);
1085     Command_63_56_bit = HAL_CMDQ_Error_Command(hnd, CMDQ_CRASH_63_56_BIT);
1086 
1087     _dbg("\033[35mCommand _bits: 0x%X, 0x%X, 0x%X, 0x%X\033[m\n", Command_63_56_bit, Command_55_32_bit, Command_31_16_bit, Command_15_0_bit);
1088     return DRVCMDQ_OK;
1089 }
1090 
1091 //--------------------------------------------------------------------------------------------------
1092 // Gen A CAF to Wait A Trigger Bus Bit
1093 // @ \b in: WaitTrigger_Bus_Command => Pointer to the CAF, we will insert WaitTrigger_Bus_Command to this struct
1094 // @ \b in: u16Tigger_ID => The trigger bit needed to be waited
1095 // @ \b in: bDetect_Falling_Mode => Check Rising/Falling Signal (0/1)
1096 //--------------------------------------------------------------------------------------------------
MDrv_CMDQv2_Gen_WaitTrigger_Bus_Command(int hnd,CAF_Struct_Pointer WaitTrigger_Bus_Command,EN_CMDQTriggerBus_ID u16Tigger_ID,MS_BOOL bDetect_Falling_Mode)1097 void MDrv_CMDQv2_Gen_WaitTrigger_Bus_Command(int hnd, CAF_Struct_Pointer WaitTrigger_Bus_Command, EN_CMDQTriggerBus_ID u16Tigger_ID, MS_BOOL bDetect_Falling_Mode)
1098 {
1099     MS_U16 u16Trgger_type;
1100 
1101     if(IsHandleValid(hnd) != DRVCMDQ_OK)
1102     {
1103         _cri("Invalid handle plz. %d\n", hnd);
1104         MS_ASSERT(0);
1105     }
1106 
1107     _dbg("\033[35mget a WaitTrigger_Bus_Command\033[m\n");
1108 
1109     switch(u16Tigger_ID)
1110     {
1111     case GE_GE2CMDQ_TRI:
1112         u16Trgger_type = HAL_GE_GE2CMDQ_TRI;
1113         break;
1114     case BDMA_INT_BDMA_0:
1115         u16Trgger_type = HAL_BDMA_INT_BDMA_0;
1116         break;
1117     case BDMA_INT_BDMA_1:
1118         u16Trgger_type = HAL_BDMA_INT_BDMA_1;
1119         break;
1120     case GPU_GPU2CMDQ_TRIG:
1121         u16Trgger_type = HAL_GPU_GPU2CMDQ_TRIG;
1122         break;
1123     case GOPG0_GOP_CMDQ_INT_0:
1124         u16Trgger_type = HAL_GOPG0_GOP_CMDQ_INT_0;
1125         break;
1126     case GOPG1_GOP_CMDQ_INT_1:
1127         u16Trgger_type = HAL_GOPG1_GOP_CMDQ_INT_1;
1128         break;
1129     case GOPG2_GOP_CMDQ_INT_2:
1130         u16Trgger_type = HAL_GOPG2_GOP_CMDQ_INT_2;
1131         break;
1132     case GOPG3_GOP_CMDQ_INT_3:
1133         u16Trgger_type = HAL_GOPG3_GOP_CMDQ_INT_3;
1134         break;
1135     case SCALAR_SC2CMDQ_TRIG_0:
1136         u16Trgger_type = HAL_SCALAR_SC2CMDQ_TRIG_0;
1137         break;
1138     case SCALAR_SC2CMDQ_TRIG_1:
1139         u16Trgger_type = HAL_SCALAR_SC2CMDQ_TRIG_1;
1140         break;
1141     case SCALAR_SC2CMDQ_TRIG_2:
1142         u16Trgger_type = HAL_SCALAR_SC2CMDQ_TRIG_2;
1143         break;
1144     case SCALAR_SC2CMDQ_TRIG_3:
1145         u16Trgger_type = HAL_SCALAR_SC2CMDQ_TRIG_3;
1146         break;
1147     case AESDMA_CMDQDMA_FINISHED:
1148         u16Trgger_type = HAL_AESDMA_CMDQDMA_FINISHED;
1149         break;
1150     case VOP_DCM2GOP_VDE:
1151         u16Trgger_type = HAL_VOP_DCM2GOP_VDE;
1152         break;
1153     case VOP_DCS2GOP_VDE:
1154         u16Trgger_type = HAL_VOP_DCS2GOP_VDE;
1155         break;
1156     case XC_DIP_CMDQ_INT:
1157         u16Trgger_type = HAL_XC_DIP_CMDQ_INT;
1158         break;
1159     case AESDMA_CMDQDMA_FINISHED_2:
1160         u16Trgger_type = HAL_AESDMA_CMDQDMA_FINISHED_2;
1161         break;
1162     case NONE_USED_SIGNAL: //AESDMA_CMDQDMA_FINISHED_2ND
1163         u16Trgger_type = 0xF;
1164         break;
1165     default:
1166         u16Trgger_type = 0xFFFF;
1167         break;
1168     }
1169 
1170     if(u16Trgger_type == 0xFFFF)
1171     {
1172         _err("\033[35mcan not gen WaitTrigger_Bus_Command\033[m\n");
1173         return;
1174     }
1175 
1176     WaitTrigger_Bus_Command->operation = 'F';    // this is wait command for trigger_bus
1177 
1178     /* the destionation_address here is used to be a decect mode setting, WaitTrigger_Bus_Command is not wait for an address!! */
1179     if(bDetect_Falling_Mode)
1180         WaitTrigger_Bus_Command->destionation_address = 1;
1181     else
1182         WaitTrigger_Bus_Command->destionation_address = 0;
1183 
1184     WaitTrigger_Bus_Command->mask = 0xFFFF & (~(1 << u16Trgger_type));
1185 }
1186 
MDrv_CMDQv2_GetWritePoint(int hnd)1187 MS_U32 MDrv_CMDQv2_GetWritePoint(int hnd)
1188 {
1189     /* this is not used, we will get Write_Pointer(buffer_wr) from shm */
1190     MS_U32 Write_Pointer = 0;
1191 
1192     if(IsHandleValid(hnd) != DRVCMDQ_OK)
1193     {
1194         _cri("Invalid handle %d\n", hnd);
1195         MS_ASSERT(0);
1196         return 0;
1197     }
1198 
1199     Write_Pointer = HAL_CMDQ_Get_Write_Pointer(hnd);
1200 
1201     _dbg("\033[35mGet Write_Pointer from RIU: 0x%X\033[m\n", (MS_U32)Write_Pointer);
1202     return Write_Pointer;
1203 }
1204 
MDrv_CMDQv2_GetConfig(int hnd,MS_PHY * SmallAddr,MS_PHY * BigAddr,MS_U32 * miu_select)1205 MS_U32 MDrv_CMDQv2_GetConfig(int hnd,MS_PHY *SmallAddr, MS_PHY *BigAddr, MS_U32 *miu_select)
1206 {
1207     MS_U32 u32ShmId, u32shmBufSize;
1208 
1209     if (FALSE == MsOS_SHM_GetId((MS_U8*)_ctx[hnd].shm_name, sizeof(ShmCtx), &u32ShmId, (MS_VIRT*)&_ctx[hnd].shm, &u32shmBufSize, MSOS_SHM_QUERY))
1210     {
1211         if (FALSE == MsOS_SHM_GetId((MS_U8*)_ctx[hnd].shm_name, sizeof(ShmCtx), &u32ShmId, (MS_VIRT*)&_ctx[hnd].shm, &u32shmBufSize, MSOS_SHM_CREATE))
1212         {
1213 	return DRVCMDQ_FAIL;
1214         }
1215     }
1216 
1217     if( _ctx[hnd].shm->buffer_start == 0 )
1218          return DRVCMDQ_FAIL;
1219 
1220     *SmallAddr = _ctx[hnd].shm->buffer_start;
1221     *BigAddr = _ctx[hnd].shm->buffer_end;
1222     *miu_select = _ctx[hnd].shm->miu_select;
1223     return DRVCMDQ_OK;
1224 }
1225 /////////////////////////////////////////////////////////////////
1226 //////// UTOPIA2 CODE ///////////////////////////////////////////
1227 /////////////////////////////////////////////////////////////////
1228 enum
1229 {
1230     CMDQ_POOL_ID_CMDQ0 = 0,
1231 } eCMDQ_PoolID;
1232 
1233 //--------------------------------------------------------------------------------------------------
1234 // Utopia2.0 will call this function to register module
1235 //--------------------------------------------------------------------------------------------------
CMDQRegisterToUtopia(FUtopiaOpen ModuleType)1236 void CMDQRegisterToUtopia(FUtopiaOpen ModuleType)
1237 {
1238     // 1. create a module(module_name, SHM_size), and register to utopia2.0
1239     void* pUtopiaModule = NULL;
1240     UtopiaModuleCreate(MODULE_CMDQ, 0, &pUtopiaModule);
1241     UtopiaModuleRegister(pUtopiaModule);
1242 
1243     // register func for module, after register here, then ap call UtopiaOpen/UtopiaIoctl/UtopiaClose can call to these registered standard func
1244     UtopiaModuleSetupFunctionPtr(pUtopiaModule, (FUtopiaOpen)CMDQOpen, (FUtopiaClose)CMDQClose, (FUtopiaIOctl)CMDQIoctl);
1245 
1246     // 2. Resource register
1247     void* psResource = NULL;
1248 
1249     // start func to add resources of a certain Resource_Pool
1250     UtopiaModuleAddResourceStart(pUtopiaModule, CMDQ_POOL_ID_CMDQ0);
1251 
1252     // create a resouce and regiter it to a certain Resource_Pool, resource can alloc private for internal use
1253     UtopiaResourceCreate("cmdq0", sizeof(CMDQ_RESOURCE_PRIVATE), &psResource);
1254     UtopiaResourceRegister(pUtopiaModule, psResource, CMDQ_POOL_ID_CMDQ0);
1255 
1256     //UtopiaResourceCreate("cmdq1", sizeof(CMDQ_RESOURCE_PRIVATE), &psResource);
1257     //UtopiaResourceRegister(pUtopiaModule, psResource, CMDQ_POOL_ID_CMDQ0);
1258 
1259     // end func to add resources of a certain Resource_Pool(this will set the ResourceSemaphore of this ResourcePool)
1260     UtopiaModuleAddResourceEnd(pUtopiaModule, CMDQ_POOL_ID_CMDQ0);
1261 
1262     // You can get the number of init times, this can prevent multiple INIT
1263     //NOTE: we only export handle 0 to utopia ioctl driver.
1264     MDrv_CMDQ_Init(_ctx[0].CMDQ_BUFFER_MIU);
1265 }
1266 
1267 //--------------------------------------------------------------------------------------------------
1268 // Utopia2.0 will call this function to get a instance to use CMDQ
1269 // @ \b in: 32ModuleVersion => this is for checking if API version is the same
1270 //--------------------------------------------------------------------------------------------------
CMDQOpen(void ** ppInstance,void * pAttribute)1271 MS_U32 CMDQOpen(void** ppInstance, void* pAttribute)
1272 {
1273     MS_U32 u32Ret = 0;
1274 #if defined(MSOS_TYPE_LINUX) || defined(MSOS_TYPE_NUTTX)
1275     // for multi-process safe, check if already other Instance exist
1276     // 1. use moduleID to get module, then try to get resource
1277     void *pModule = NULL;
1278     void *pResource = NULL;
1279     UtopiaModuleGetPtr(MODULE_CMDQ, &pModule);
1280 
1281     if(UtopiaResourceObtain(pModule, CMDQ_POOL_ID_CMDQ0, &pResource) != 0)
1282     {
1283         _err("UtopiaResourceObtainToInstant fail\n");
1284         return 1;
1285     }
1286 
1287     // if get a resource, check the module private SHM(default to be 0, only create at the first time) to decide whether this process can open instance
1288     void *pCMDQResPri = NULL;
1289     UtopiaResourceGetPrivate(pResource, &pCMDQResPri);
1290 
1291     if(*(MS_U32 *)pCMDQResPri == 0)
1292     {
1293         *(MS_U32 *)pCMDQResPri = 1;
1294         UtopiaResourceRelease(pResource);
1295     }
1296     else
1297     {
1298         _err("\033[35m[CMDQ INFO] can not open an INSTANCE\033[m\n"); // joe.liu
1299         UtopiaResourceRelease(pResource);
1300         return 1;
1301     }
1302 #endif
1303 
1304     _dbg("\033[35m[CMDQ INFO] OPEN INSTANCE...\033[m\n"); // joe.liu
1305     CMDQ_INSTANT_PRIVATE *pCMDQPri = NULL;
1306 
1307     // instance is allocated here, also can allocate private for internal use, ex, CMDQ_INSTANT_PRIVATE, ppInstance will point to a pointer of the created UTOPIA_INSTANCE
1308     u32Ret = UtopiaInstanceCreate(sizeof(CMDQ_INSTANT_PRIVATE), ppInstance);
1309     if(u32Ret)
1310     {
1311         _err("\033[35m[CMDQ OPEN] Create Instance Failed!!\033[m\n");
1312         return 1;
1313     }
1314     // set the pCMDQPri point to the private of UTOPIA_INSTANCE
1315     UtopiaInstanceGetPrivate(*ppInstance, (void**)&pCMDQPri);
1316 
1317     // setup func in private and assign the calling func in func ptr in instance private
1318     pCMDQPri->fpCMDQGetLibVer = (IOCTL_CMDQ_GETLIBVER)MDrv_CMDQ_GetLibVer;
1319     pCMDQPri->fpCMDQPrintf_Crash_Command = (IOCTL_CMDQ_PRINTFCRASHCOMMAND)MDrv_CMDQ_Printf_Crash_Command;
1320     pCMDQPri->fpCMDQReceive = (IOCTL_CMDQ_RECEIVE)MDrv_CMDQ_Receive;
1321     pCMDQPri->fpCMDQSet_Timer_Ratio = (IOCTL_CMDQ_SETTIMERRATIO)MDrv_CMDQ_Set_timer_ratio;
1322     pCMDQPri->fpCMDQSetDbgLevel = (IOCTL_CMDQ_SETDBGLEVEL)MDrv_CMDQ_SetDbgLevel;
1323 
1324     // 0 is pass for UtopiaOpen
1325     return 0;
1326 }
1327 
CMDQIoctl(void * pInstance,MS_U32 u32Cmd,void * pArgs)1328 MS_U32 CMDQIoctl(void* pInstance, MS_U32 u32Cmd, void* pArgs)
1329 {
1330     void* pModule = NULL;
1331     UtopiaInstanceGetModule(pInstance, &pModule);
1332 
1333     CMDQ_INSTANT_PRIVATE* psCMDQInstPri = NULL;
1334     UtopiaInstanceGetPrivate(pInstance, (void**)&psCMDQInstPri);
1335 
1336     PCMDQ_GETLIBVER_PARAM pGetLibVerParam = NULL;
1337     PCMDQ_RECEIVE_PARAM pReceiveParam = NULL;
1338     PCMDQ_SETTIMERRATIO_PARAM pSetTimerRatioParam = NULL;
1339     PCMDQ_SETDBGLEVEL_PARAM pSetDbgLevelParam = NULL;
1340 
1341     MS_U32 u32Ret;
1342 
1343     // no need to get resource, only one instance at one time
1344     switch(u32Cmd)
1345     {
1346         case MDrv_CMD_CMDQ_GetLibVer:
1347             _dbg("CMDQIoctl - MDrv_CMD_CMDQ_GetLibVer\n");
1348             pGetLibVerParam = (PCMDQ_GETLIBVER_PARAM)pArgs;
1349             u32Ret = (MS_U32)psCMDQInstPri->fpCMDQGetLibVer(pGetLibVerParam->ppVersion);
1350             return u32Ret;
1351         case MDrv_CMD_CMDQ_Printf_Crash_Command:
1352             _dbg("CMDQIoctl - MDrv_CMD_CMDQ_Printf_Crash_Command\n");
1353             u32Ret = (MS_U32)psCMDQInstPri->fpCMDQPrintf_Crash_Command();
1354             return u32Ret;
1355         case MDrv_CMD_CMDQ_Receive:
1356             _dbg("CMDQIoctl - MDrv_CMD_CMDQ_Receive\n");
1357             pReceiveParam = (PCMDQ_RECEIVE_PARAM)pArgs;
1358             u32Ret = (MS_U32)psCMDQInstPri->fpCMDQReceive(pReceiveParam->New_IP_Head);
1359             return u32Ret;
1360         case MDrv_CMD_CMDQ_Set_timer_ratio:
1361             _dbg("CMDQIoctl - MDrv_CMD_CMDQ_Set_timer_ratio\n");
1362             pSetTimerRatioParam = (PCMDQ_SETTIMERRATIO_PARAM)pArgs;
1363             u32Ret = (MS_U32)psCMDQInstPri->fpCMDQSet_Timer_Ratio(pSetTimerRatioParam->time, pSetTimerRatioParam->ratio);
1364             return u32Ret;
1365         case MDrv_CMD_CMDQ_SetDbgLevel:
1366             _dbg("CMDQIoctl - MDrv_CMD_CMDQ_SetDbgLevel\n");
1367             pSetDbgLevelParam = (PCMDQ_SETDBGLEVEL_PARAM)pArgs;
1368             u32Ret = (MS_U32)psCMDQInstPri->fpCMDQSetDbgLevel(pSetDbgLevelParam->DbgLevel);
1369             return u32Ret;
1370         default:
1371             break;
1372     };
1373 
1374     return 1; // FIXME: error code(if no this cmd, return fail)
1375 }
1376 
CMDQClose(void * pInstance)1377 MS_U32 CMDQClose(void* pInstance)
1378 {
1379     UtopiaInstanceDelete(pInstance);
1380 
1381 #if defined(MSOS_TYPE_LINUX) || defined(MSOS_TYPE_NUTTX)
1382     // Restore resource pri_shm content
1383     // 1. use moduleID to get module, then try to get resource
1384     void *pModule = NULL;
1385     void *pResource = NULL;
1386     UtopiaModuleGetPtr(MODULE_CMDQ, &pModule);
1387 
1388     if(UtopiaResourceObtain(pModule, CMDQ_POOL_ID_CMDQ0, &pResource) != 0)
1389     {
1390         _err("UtopiaResourceObtainToInstant fail\n");
1391         return 1;
1392     }
1393 
1394     // if get a resource, check the module private SHM(default to be 0, only create at the first time) to decide whether this process can open instance
1395     void *pCMDQResPri = NULL;
1396     UtopiaResourceGetPrivate(pResource, &pCMDQResPri);
1397 
1398     if(*(MS_U32 *)pCMDQResPri == 0)
1399     {
1400         _err("\033[35m[CMDQClose] Strange resource pri_shm content!!\033[m\n"); // joe.liu
1401         UtopiaResourceRelease(pResource);
1402         return 1;
1403     }
1404     else
1405     {
1406         _dbg("\033[35m[Multi-process Safe] Release an Instance!!\033[m\n");
1407         *(MS_U32 *)pCMDQResPri = 0;
1408         UtopiaResourceRelease(pResource);
1409         return 0;
1410     }
1411 #endif
1412 
1413     return 0;
1414 }
1415 
MDrv_CMDQv2_SetPowerState(int hnd,EN_POWER_MODE u16PowerState)1416 MS_U32 MDrv_CMDQv2_SetPowerState(int hnd, EN_POWER_MODE u16PowerState)
1417 {
1418     static EN_POWER_MODE _prev_u16PowerState = E_POWER_MECHANICAL;
1419     MS_U32 u32Return = UTOPIA_STATUS_FAIL;
1420     MS_U32 u32Ret, u32ShmId, u32shmBufSize;
1421     MS_VIRT u32shmAddr;
1422 
1423     MS_U32 u32STR_cmdq_miu_select;
1424     MS_PHY u32STR_cmdq_buffer_start, u32STR_cmdq_buffer_end;
1425     MS_VIRT u32VIRT_Buffer_Start;
1426     MS_PHY pa_start;
1427 
1428     _msg("\033[35mdoing MDrv_CMDQ_SetPowerState with u16PowerState is %d\033[m\n", u16PowerState);
1429     _dbg("\033[35mdoing MDrv_CMDQ_SetPowerState with u16PowerState is %d\033[m\n", u16PowerState);
1430     _err("\033[35mdoing MDrv_CMDQ_SetPowerState with u16PowerState is %d\033[m\n", u16PowerState);
1431     _cri("\033[35mdoing MDrv_CMDQ_SetPowerState with u16PowerState is %d\033[m\n", u16PowerState);
1432 
1433     if (u16PowerState == E_POWER_SUSPEND)
1434     {
1435         _prev_u16PowerState = u16PowerState;
1436         u32Return = UTOPIA_STATUS_SUCCESS; //SUSPEND_OK
1437     }
1438     else if (u16PowerState == E_POWER_RESUME)
1439     {
1440         if (_prev_u16PowerState == E_POWER_SUSPEND)    // we set E_POWER_SUSPEND, and then set E_POWER_RESUME
1441         {
1442             _prev_u16PowerState = u16PowerState;
1443             IS_STR_RESUME = 1;
1444 
1445             /* get a str_flag */
1446             u32Ret = MsOS_SHM_GetId((MS_U8*)"cmdq_str_flag", sizeof(MS_U32), &u32ShmId, &u32shmAddr, &u32shmBufSize, MSOS_SHM_QUERY);
1447             if(u32Ret == TRUE)
1448             {
1449                 *(MS_U32*)u32shmAddr = IS_STR_RESUME;
1450                 _dbg("\033[35mset cmdq_str_flag to be %d\033[m\n", IS_STR_RESUME);
1451             }
1452             else
1453             {
1454                 _err("\033[35mget str_flag failed!!!\033[m\n");
1455                 MS_ASSERT(0);
1456                 return UTOPIA_STATUS_FAIL;
1457             }
1458 
1459             u32Ret = MsOS_SHM_GetId((MS_U8*)_ctx[hnd].shm_name, sizeof(ShmCtx), &u32ShmId, (MS_VIRT*)&_ctx[hnd].shm, &u32shmBufSize, MSOS_SHM_QUERY);
1460             if(u32Ret != TRUE)
1461             {
1462                 _cri("FAIL TO ACCES SHM. can not do anything here. assert(0)!!!\n");
1463                 u32STR_cmdq_miu_select = MIU_NOT_SUPPORT;
1464                 u32STR_cmdq_buffer_start = 0;
1465                 u32STR_cmdq_buffer_end = 0;
1466                 MS_ASSERT(0);
1467             }
1468             else
1469             {
1470                 u32STR_cmdq_miu_select   = _ctx[hnd].shm->miu_select;
1471                 _dbg("do cmdq_init for miu %d\033[m\n", u32STR_cmdq_miu_select);
1472                 u32STR_cmdq_buffer_start = _ctx[hnd].shm->buffer_start;
1473                 u32STR_cmdq_buffer_end   = _ctx[hnd].shm->buffer_end;
1474             }
1475             MDrv_CMDQ_Init(u32STR_cmdq_miu_select);
1476             MDrv_CMDQ_Get_Memory_Size(u32STR_cmdq_buffer_start, u32STR_cmdq_buffer_end, u32STR_cmdq_miu_select);
1477 
1478             /* clear cmdq_buffer(non-cache) */
1479 
1480                 _dbg("\033[35mbuffer clear for MIU1 CMDQ_BUFFER\033[m\n");
1481             _miu_offset_to_phy(u32STR_cmdq_miu_select,0,pa_start);
1482             u32VIRT_Buffer_Start = MS_PA2KSEG1(u32STR_cmdq_buffer_start + pa_start);
1483             if(u32VIRT_Buffer_Start == NULL)
1484             {
1485                 _dbg("\033[35mu32VIRT_Buffer_Start is 0x%X, not mapped\033[m\n", (unsigned int)u32VIRT_Buffer_Start);
1486             }
1487             else
1488             {
1489                 memset((void *)u32VIRT_Buffer_Start, 0 , (u32STR_cmdq_buffer_end - u32STR_cmdq_buffer_start));
1490             }
1491 
1492             u32Return = UTOPIA_STATUS_SUCCESS; //RESUME_OK
1493         }
1494         else
1495         {
1496             _err("[%s,%5d]It is not suspended yet. We should not resume\n");
1497             u32Return = UTOPIA_STATUS_FAIL; //SUSPEND_FAILED
1498         }
1499 		IS_STR_RESUME = 0;  /* set IS_STR_RESUME to 0, this is because all STR_RESUME action is done */
1500     }
1501     else
1502     {
1503         _err("[%s,%5d]Do Nothing: %d\n",u16PowerState);
1504         u32Return = UTOPIA_STATUS_FAIL;
1505     }
1506 
1507     return u32Return;
1508 }
1509 
1510 
1511 ///Get current number of command can be pushed into buffer (free slot)
MDrv_CMDQv2_Get_FreeCmdLine_Size(int hnd)1512 MS_U32 MDrv_CMDQv2_Get_FreeCmdLine_Size(int hnd) {
1513     MS_PHY s, e, r, w;
1514 
1515     s = _ctx[hnd].buffer_start;
1516     e = _ctx[hnd].buffer_end;
1517     w = _ctx[hnd].buffer_wr;
1518     r = HAL_CMDQ_Read_Pointer(hnd);
1519 
1520     //@NOTE need to handle out of range and rdptr reseted value.
1521     if(r > e || r < s)
1522     {   _err("buffer_start=%#x, buffer_end=%#x, buffer_wr=%#x\n", s, e, w);
1523         _err("rdptr = %08x, out of buffer range.\n", r);
1524         _err("we assume CMDQ was in inited status.\n");
1525         //return _ctx[hnd].TOTAL_BUFFER_SIZE;
1526         r = s;
1527     }
1528 
1529     if(_ctx[hnd].CMDQ_MODE == RING_BUFFER_MODE)
1530     {
1531         //@NOTE: actually, rdptr will equal to wrptr.
1532         if (w==r) {
1533             //@NOTE: because if we fill buffer full, that rd=wr will not trigger.
1534             return _ctx[hnd].TOTAL_BUFFER_SIZE-1;
1535         } else if ( r > w ) {
1536             //|S|......W_________R......|E|
1537             return (r-w);
1538         } else if ( w > r ) {
1539             //|S|______R.........W______|E|
1540             return ((r-s)+(e-w)+1);
1541         } else {
1542             _cri("Internal error!\n");
1543         }
1544         return 0;
1545     }
1546     else
1547     {
1548         _cri("We only support RING_BUFFER_MODE ONLY!\n");
1549         MS_ASSERT(0);
1550     }
1551     return 0;
1552 }
1553 
1554 //--------------------------------------------------------------------------------------------------
1555 //  Debug function.
1556 //--------------------------------------------------------------------------------------------------
MDrv_CMDQv2_Dbg_WriteDummy(int hnd,MS_U32 value)1557 void MDrv_CMDQv2_Dbg_WriteDummy(int hnd, MS_U32 value) {
1558     HAL_CMDQ_Write_Dummy_Register(hnd, value);
1559 }
1560 
MDrv_CMDQv2_Dbg_ReadDummy(int hnd)1561 MS_U32 MDrv_CMDQv2_Dbg_ReadDummy(int hnd) {
1562     return HAL_CMDQ_Read_Dummy_Register(hnd);
1563 }
1564 
MDrv_CMDQv2_Dbg_Pause(int hnd)1565 void MDrv_CMDQv2_Dbg_Pause(int hnd) {
1566     HAL_CMDQ_Reset2(hnd, 0);
1567 }
1568 
MDrv_CMDQv2_Dbg_Continue(int hnd)1569 void MDrv_CMDQv2_Dbg_Continue(int hnd) {
1570     HAL_CMDQ_Reset2(hnd, 1);
1571 }
1572 
MDrv_CMDQv2_DumpContext(void)1573 void MDrv_CMDQv2_DumpContext(void)
1574 {
1575     int i;
1576     MS_U32 r;
1577 
1578     _dbg("-- Total %d CMDQ HW ----------------------------------------------------\n", NUMBER_OF_CMDQ_HW);
1579     for(i=0;i<NUMBER_OF_CMDQ_HW;i++)
1580     {
1581         _dbg(" ====================================================== CMDQ #%d ===============\n", i);
1582         _dbg(" Mode: (%d) %s\n",
1583              _ctx[i].CMDQ_MODE, (_ctx[i].CMDQ_MODE==0)?"ALWAYS_WORK":"TRIGGER_MODE");
1584 
1585         _dbg(" Basis: miu     size              start -                end             wr_ptr\n");
1586         _dbg("        %3d %8lu 0x%016llX - 0x%016llX 0x%016llX\n",
1587              _ctx[i].CMDQ_BUFFER_MIU, _ctx[i].TOTAL_BUFFER_SIZE,
1588              _ctx[i].buffer_start, _ctx[i].buffer_end, _ctx[i].buffer_wr);
1589 
1590 
1591         _dbg(" Shm:       init miu              start -                end             wr_ptr\n");
1592         if(_ctx[i].shm != NULL)
1593         {
1594             _dbg("      %10s %3d 0x%016llX - 0x%016llX 0x%016llX\n",
1595                  (_ctx[i].shm->init==0)?"NOINIT":"INITED", _ctx[i].shm->miu_select,
1596                  _ctx[i].shm->buffer_start, _ctx[i].shm->buffer_end,
1597                  _ctx[i].shm->buffer_wr);
1598         }
1599         else
1600         {
1601             _dbg("      SHM not allocated yet.\n");
1602             continue;
1603         }
1604 
1605         _dbg(" rdptr: 0x%016llX\n", HAL_CMDQ_Read_Pointer(i));
1606 
1607         _dbg(" Stats: cmd_setcount    cmd_count     null_cnt\n");
1608         _dbg("        %12lu %12lu %12lu\n",
1609              _ctx[i].stats.cmd_setcount, _ctx[i].stats.cmd_count, _ctx[i].stats.cmd_nullcnt);
1610 
1611         r = HAL_CMDQ_Read_Misc_Status(i);
1612         _dbg(" Misc: cmdptr %s, sram %s, sram bist %s\n",
1613              (r&CMDQ_CMD_PTR_VLD)?"  VALID":"INVALID",
1614              (r&CMDQ_RD_SRAM_EMPTY)?" EMPTY":"!EMPTY",
1615              (r&CMDQ_SRAM_BIST_FAIL)?"FAIL":"  OK");
1616 
1617         r = HAL_CMDQ_Get_Debug_Step_Mode(i);
1618         _dbg(" Debug: debug mode %s, step mode %s\n",
1619              (r&CMDQ_DEBUG_MODE_ENABLE)?"ON":"OFF",
1620              (r&CMDQ_DEBUG_ONESTEP_ENABLE)?"DEBUG_MODE":"NORMAL_MODE");
1621 
1622         //access some statics or debug-assisted register here. Ex. IRQ
1623         {
1624             MS_PHY s, e, r, w;
1625             s = _ctx[i].buffer_start;
1626             e = _ctx[i].buffer_end;
1627             w = _ctx[i].buffer_wr;
1628             r = HAL_CMDQ_Read_Pointer(i);
1629             _dbg("s,e,w,r: %16llx, %16llx, %16llx, %16llx\n", s,e,w,r);
1630         }
1631 
1632     }
1633     _dbg("-- CMDQ Dump Context ----------------------------------------------------------\n");
1634 }
1635 
1636 
1637