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