1 /*
2  *  Routines to access hardware
3  *
4  *  Copyright (c) 2013 Realtek Semiconductor Corp.
5  *
6  *  This module is a confidential and proprietary property of RealTek and
7  *  possession or use of this module requires written permission of RealTek.
8  */
9 #include "ameba_soc.h"
10 #include <stdarg.h>
11 #include "strproc.h"
12 
13 #include "k_api.h"
14 
15 SHELL_ROM_BSS_SECTION volatile UART_LOG_CTL	 shell_ctl;
16 SHELL_ROM_BSS_SECTION u8						*shell_argv_array[MAX_ARGV];
17 SHELL_ROM_BSS_SECTION UART_LOG_BUF			shell_buf;
18 #ifdef CONFIG_UART_LOG_HISTORY
19 SHELL_ROM_BSS_SECTION u8						shell_history_cmd[UART_LOG_HISTORY_LEN][UART_LOG_CMD_BUFLEN];
20 #endif
21 SHELL_ROM_BSS_SECTION u32					shell_recv_all_data_onetime;
22 
23 //=================================================
24 
25 //======================================================
26 //<Function>:  shell_array_init
27 //<Usage   >:  This function is to initialize an array with a given value.
28 //<Argus    >:  pArrayToInit --> pointer to an array
29 //                   ArrayLen      --> number of array elements
30 //                   InitValue     --> initial value for the array
31 //<Return   >:  VOID
32 //<Notes    >:  NA
33 //======================================================
34 SHELL_ROM_TEXT_SECTION _LONG_CALL_
shell_array_init(u8 * pArrayToInit,u8 ArrayLen,u8 InitValue)35 VOID shell_array_init(u8  *pArrayToInit,  u8  ArrayLen,  u8  InitValue)
36 {
37 	u8  ItemCount =0;
38 
39 	for (ItemCount=0; ItemCount<ArrayLen; ItemCount++){
40 		*(pArrayToInit+ItemCount) = InitValue;
41 	}
42 }
43 
44 
45 //======================================================
46 //<Function>:  shell_get_argc
47 //<Usage   >:  This function is to calcute how many parameters in the cmd string
48 //<Argus    >:  string      --> pointer to an input cmd string
49 //<Return   >:  number of parameters in the string.(****except the cmd itself****)
50 //<Notes    >:  NA
51 //======================================================
52 SHELL_ROM_TEXT_SECTION _LONG_CALL_
shell_get_argc(const u8 * string)53 u8 shell_get_argc(const   u8  *string)
54 {
55 	u16 argc;
56 	u8  *pStr;
57 
58 	argc = 0;
59 	pStr = (u8 *)string;
60 
61 	while(*pStr){
62 		if ((*pStr != ' ') && (*pStr)){
63 			argc++;
64 			while ((*pStr != ' ') && (*pStr)){
65 				pStr++;
66 			}
67 
68 			continue;
69 		}
70 
71 		pStr++;
72 	}
73 
74 	if (argc >= MAX_ARGV){
75 		argc = MAX_ARGV - 1;
76 	}
77 
78 	return argc;
79 }
80 
81 //======================================================
82 //<Function>:  shell_get_argv
83 //<Usage   >:  This function is to transfer a cmd string to a char array.
84 //<Argus    >:  string      --> pointer to an input cmd string
85 //<Return   >:  pointer to a char array
86 //<Notes    >:  NA
87 //======================================================
88 SHELL_ROM_TEXT_SECTION _LONG_CALL_
shell_get_argv(const u8 * string)89 u8** shell_get_argv(const   u8  *string)
90 {
91 	u8  ArgvCount = 0;
92 	u8  *pStr;
93 
94 	shell_array_init((u8*)shell_argv_array, MAX_ARGV*sizeof(char *), 0);
95 	pStr = (u8 *)string;
96 
97 	while(*pStr){
98 		shell_argv_array[ArgvCount] = pStr;
99 		while((*pStr != ' ') && (*pStr)){
100 			pStr++;
101 		}
102 
103 		*(pStr++) = '\0';
104 
105 		while((*pStr == ' ') && (*pStr)){
106 			pStr++;
107 		}
108 
109 		ArgvCount++;
110 
111 		if (ArgvCount == MAX_ARGV){
112 			break;
113 		}
114 	}
115 
116 	return (u8 **)&shell_argv_array;
117 }
118 
119 
120 
121 
122 //======================================================
123 //<Function>:  shell_cmd_exec_rom
124 //<Usage   >:  This function is to parse Uart-Log cmds. If there's a matched
125 //                      one, it goes to execute that.
126 //<Argus    >:  pointer to Uart-Log cmd temp buffer
127 //<Return   >:  VOID
128 //<Notes    >:  NA
129 //======================================================
130 SHELL_ROM_TEXT_SECTION _LONG_CALL_
shell_cmd_exec_rom(PUART_LOG_CTL pUartLogCtlExe)131 static VOID shell_cmd_exec_rom(PUART_LOG_CTL   pUartLogCtlExe)
132 {
133 	u8  CmdCnt = 0;
134 	u8  argc = 0;
135 	u8  **argv;
136 	u32  CmdNum;
137 	PUART_LOG_BUF   pUartLogBuf = pUartLogCtlExe->pTmpLogBuf;
138 	PCOMMAND_TABLE pCmdTbl = pUartLogCtlExe->pCmdTbl;
139 
140 	argc = shell_get_argc((const u8*)&((*pUartLogBuf).UARTLogBuf[0]));
141 	argv = shell_get_argv((const u8*)&((*pUartLogBuf).UARTLogBuf[0]));
142 	CmdNum = pUartLogCtlExe->CmdTblSz;
143 
144 	if (argc > 0){
145 		_strupr(argv[0]);
146 
147 		for (CmdCnt = 0; CmdCnt< CmdNum; CmdCnt++){
148 			if ((_strcmp((const char*)argv[0], (const char*)(pCmdTbl[CmdCnt].cmd)))==0){
149 				pCmdTbl[CmdCnt].func((argc-1) , (argv+1));
150 				shell_array_init(argv[0], sizeof(argv[0]) ,0);
151 				break;
152 			}
153 		}
154 	}
155 
156 	(*pUartLogBuf).BufCount = 0;
157 	shell_array_init(&(*pUartLogBuf).UARTLogBuf[0], UART_LOG_CMD_BUFLEN, '\0');
158 }
159 
160 
161 //======================================================
162 //<Function>:  shell_show_backspace
163 //<Usage   >:  To dispaly backspace on the target interface.
164 //<Argus    >:  BackLen      --> backspace number to show
165 //                   EchoFlag     --> a control flag to show msg or not.
166 //                   pfINPUT      --> func pointer to the display function
167 //<Return   >:  VOID
168 //<Notes    >:  NA
169 //======================================================
170 SHELL_ROM_TEXT_SECTION _LONG_CALL_
shell_show_backspace(u8 BackLen,u8 EchoFlag,VOID * pfINPUT)171 static VOID shell_show_backspace(u8  BackLen, u8  EchoFlag, VOID *pfINPUT)
172 {
173 	u8  BackCnt;
174 	ECHOFUNC pfEcho;
175 	pfEcho = (ECHOFUNC)pfINPUT;
176 
177 	for(BackCnt=0; BackCnt<BackLen; BackCnt++){
178 		if (EchoFlag){
179 			pfEcho((u8*)"%c",KB_ASCII_BS);
180 			pfEcho((u8*)" ");
181 			pfEcho((u8*)"%c",KB_ASCII_BS);
182 		}
183 	}
184 }
185 
186 //======================================================
187 //<Function>:  shell_recall_oldcmd
188 //<Usage   >:  To retrieve the old cmd and may show it on the target interface.
189 //<Argus    >:  pTmpBuf      --> cmd temp buffer, the retrieved cmd will be stored in
190 //                                            it.
191 //                   OldBuf         --> pointer to an cmd buffer.
192 //                   EchoFlag      --> a control flag to show msg or not.
193 //                   pfINPUT       --> func pointer to the display function
194 //<Return   >:  VOID
195 //<Notes    >:  NA
196 //======================================================
197 #ifdef CONFIG_UART_LOG_HISTORY
198 SHELL_ROM_TEXT_SECTION _LONG_CALL_
shell_recall_oldcmd(PUART_LOG_BUF pTmpBuf,u8 * OldBuf,u8 EchoFlag,VOID * pfINPUT)199 static VOID shell_recall_oldcmd(
200 	PUART_LOG_BUF  pTmpBuf,
201 	u8  *OldBuf,
202 	u8  EchoFlag,
203 	VOID *pfINPUT)
204 {
205 
206 	ECHOFUNC pfEcho;
207 	pfEcho = (ECHOFUNC)pfINPUT;
208 
209 	_strcpy((char*)&((*pTmpBuf).UARTLogBuf[0]), (char*)OldBuf);
210 	(*pTmpBuf).BufCount = _strlen((char*)&(*pTmpBuf).UARTLogBuf[0]);
211 
212 	if (EchoFlag){
213 		pfEcho(&((*pTmpBuf).UARTLogBuf[0]));
214 	}
215 
216 }
217 
218 //======================================================
219 //<Function>:  shell_cmd_history
220 //<Usage   >:  To deal with history-cmds, get the next/previous cmd and show it.
221 //<Argus    >:  RevData         --> a received data.
222 //                   prvUartLogCtl  --> pointer to UART_LOG_CTL
223 //                   EchoFlag        --> a control flag to show msg or not.
224 //<Return   >:  VOID
225 //<Notes    >:  NA
226 //======================================================
227 SHELL_ROM_TEXT_SECTION _LONG_CALL_
shell_cmd_history(u8 RevData,UART_LOG_CTL * prvUartLogCtl,u8 EchoFlag)228 VOID shell_cmd_history(
229 	u8  RevData,
230 	UART_LOG_CTL    *prvUartLogCtl,
231 	u8  EchoFlag)
232 {
233 	ECHOFUNC pfEcho;
234 	pfEcho = (ECHOFUNC)(*prvUartLogCtl).pfINPUT;
235 
236 	if (RevData == 'A'){
237 		if ((*prvUartLogCtl).CRSTS == 0){
238 			if ((*prvUartLogCtl).RevdNo > 0){
239 				if ((*prvUartLogCtl).SeeIdx == 0){
240 					(*prvUartLogCtl).SeeIdx = (*prvUartLogCtl).RevdNo - 1;
241 				}
242 				else{
243 					(*prvUartLogCtl).SeeIdx--;
244 				}
245 			}
246 		}
247 
248 		shell_show_backspace((*(*prvUartLogCtl).pTmpLogBuf).BufCount, EchoFlag, pfEcho);
249 
250 		if ((*prvUartLogCtl).RevdNo > 0){
251 			shell_recall_oldcmd((*prvUartLogCtl).pTmpLogBuf , (u8*)&(*prvUartLogCtl).pHistoryBuf[(*prvUartLogCtl).SeeIdx],
252 				1, (VOID*)pfEcho);
253 
254 		}
255 
256 		(*prvUartLogCtl).CRSTS = 0;
257 
258 	}
259 	else if (RevData == 'B'){
260 
261 		if ((*prvUartLogCtl).RevdNo > 0){
262 			if ((*prvUartLogCtl).SeeIdx == ((*prvUartLogCtl).RevdNo-1)){
263 				(*prvUartLogCtl).SeeIdx = 0;
264 			}
265 			else{
266 				(*prvUartLogCtl).SeeIdx++;
267 			}
268 		}
269 
270 		shell_show_backspace(((*(*prvUartLogCtl).pTmpLogBuf).BufCount), 1, pfEcho);
271 
272 		if ((*prvUartLogCtl).RevdNo > 0){
273 			shell_recall_oldcmd((*prvUartLogCtl).pTmpLogBuf, (u8*)&(*prvUartLogCtl).pHistoryBuf[(*prvUartLogCtl).SeeIdx],
274 				1, (VOID*)pfEcho);
275 		}
276 
277 		(*prvUartLogCtl).CRSTS = 0;
278 
279 	}
280 }
281 #endif
282 
283 //======================================================
284 //<Function>:  shell_cmd_chk
285 //<Usage   >:  To deal with Uart-Log input characters
286 //<Argus    >:  RevData         --> a received data.
287 //                   prvUartLogCtl  --> pointer to UART_LOG_CTL
288 //                   EchoFlag        --> a control flag to show msg or not.
289 //<Return   >:  VOID
290 //<Notes    >:  NA
291 //======================================================
292 SHELL_ROM_TEXT_SECTION _LONG_CALL_
shell_cmd_chk(u8 RevData,UART_LOG_CTL * prvUartLogCtl,u8 EchoFlag)293 u8 shell_cmd_chk(
294 	u8  RevData,
295 	UART_LOG_CTL    *prvUartLogCtl,
296 	u8  EchoFlag)
297 {
298 	u8  RTNSTS = 0;
299 	u8  SpaceCount = 0;
300 
301 	//Cast the input function pointer to the actual echo function pointer type-----
302 	ECHOFUNC pfEcho;
303 	pfEcho = (ECHOFUNC)(*prvUartLogCtl).pfINPUT;
304 	//----------------------------------------------------------------
305 
306 	if (((*(*prvUartLogCtl).pTmpLogBuf).BufCount<(UART_LOG_CMD_BUFLEN-1)) ||
307 	(((*(*prvUartLogCtl).pTmpLogBuf).BufCount==(UART_LOG_CMD_BUFLEN-1)) &&
308 	((RevData == KB_ASCII_CR)||(RevData == '\0')||
309 	(RevData == KB_ASCII_BS) || (RevData == KB_ASCII_BS_7F)))){
310 
311 		if (RevData == 0xFF){   //invlid char, ignore it
312 			RTNSTS = 1;
313 		}
314 
315 		if (RevData == KB_ASCII_LF){
316 			RTNSTS = 1;
317 		}
318 		else if ((RevData == KB_ASCII_CR)||(RevData == '\0')){
319 			RTNSTS = 2;
320 			(*prvUartLogCtl).CRSTS = 1;
321 			(*(*prvUartLogCtl).pTmpLogBuf).UARTLogBuf[(*(*prvUartLogCtl).pTmpLogBuf).BufCount] = '\0';
322 			if (EchoFlag){
323 				pfEcho((u8*)"\r\n");
324 			}
325 
326 			if((*(*prvUartLogCtl).pTmpLogBuf).BufCount != 0)
327 			{
328 #ifdef CONFIG_UART_LOG_HISTORY
329 				_strcpy((u8*)&((*prvUartLogCtl).pHistoryBuf[(*prvUartLogCtl).NewIdx]),
330 				    (const u8*)&((*(*prvUartLogCtl).pTmpLogBuf).UARTLogBuf));
331 
332 				((*prvUartLogCtl).RevdNo < UART_LOG_HISTORY_LEN) ?
333 				((*prvUartLogCtl).RevdNo++) : ((*prvUartLogCtl).RevdNo = UART_LOG_HISTORY_LEN);
334 
335 				(*prvUartLogCtl).SeeIdx = (*prvUartLogCtl).NewIdx;
336 				((*prvUartLogCtl).NewIdx < (UART_LOG_HISTORY_LEN-1)) ?
337 				((*prvUartLogCtl).NewIdx++) : ((*prvUartLogCtl).NewIdx = 0);
338 
339 
340 #endif
341 
342 			}
343 		}
344 		else if ((RevData == KB_ASCII_BS) || (RevData == KB_ASCII_BS_7F)){
345 			RTNSTS = 1;
346 
347 			if ((*(*prvUartLogCtl).pTmpLogBuf).BufCount > 0){
348 				(*(*prvUartLogCtl).pTmpLogBuf).BufCount--;
349 
350 				shell_show_backspace(1,1,(VOID *)pfEcho);
351 			}
352 		}
353 		else if (RevData == KB_ASCII_TAB){  //the TAB is fixed to be one space(' ')
354 			RTNSTS = 1;
355 			for(SpaceCount=0; SpaceCount< KB_SPACENO_TAB; SpaceCount++){
356 				(*(*prvUartLogCtl).pTmpLogBuf).UARTLogBuf[(*(*prvUartLogCtl).pTmpLogBuf).BufCount] = ' ';
357 				(*(*prvUartLogCtl).pTmpLogBuf).BufCount++;
358 			}
359 
360 			if (EchoFlag){
361 				pfEcho((u8 *)" ");
362 			}
363 
364 		}
365 		else{
366 			RTNSTS = 1;
367 			if (EchoFlag){
368 				pfEcho((u8*)"%c",RevData);
369 			}
370 
371 			(*(*prvUartLogCtl).pTmpLogBuf).UARTLogBuf[(*(*prvUartLogCtl).pTmpLogBuf).BufCount] = RevData;
372 			(*(*prvUartLogCtl).pTmpLogBuf).BufCount++;
373 		}
374 	}
375 	else if ((*(*prvUartLogCtl).pTmpLogBuf).BufCount==(UART_LOG_CMD_BUFLEN-1)){
376 		RTNSTS = 1;
377 
378 		pfEcho((u8*)"\n\r <<<Too long cmd string.>>> \n");
379 		(*(*prvUartLogCtl).pTmpLogBuf).UARTLogBuf[(*(*prvUartLogCtl).pTmpLogBuf).BufCount] = '\0';
380 		pfEcho(&(*(*prvUartLogCtl).pTmpLogBuf).UARTLogBuf[0]);
381 	}
382 
383 	return RTNSTS;
384 }
385 
386 
387 //======================================================
388 //<Function>:  shell_uart_irq_rom
389 //<Usage   >:  To deal with Uart-Log RX IRQ
390 //<Argus    >:  VOID
391 //<Return   >:  VOID
392 //<Notes    >:  NA
393 //======================================================
394 SHELL_ROM_TEXT_SECTION _LONG_CALL_
shell_uart_irq_rom(VOID * Data)395 VOID shell_uart_irq_rom(VOID * Data)
396 {
397 	krhino_intrpt_enter();
398 	/* To avoid gcc warnings */
399 	( void ) Data;
400 
401 	u8      UartReceiveData = 0;
402 	//For Test
403 	BOOL    PullMode = _FALSE;
404 	u32 IrqEn = LOGUART_GetIMR();
405 
406 	LOGUART_SetIMR(0);
407 
408 recv_again:
409 	UartReceiveData = LOGUART_GetChar(PullMode);
410 
411     extern int g_uart_init;
412     if(g_uart_init != 0)
413     {
414         extern size_t uart0_rx_buffer_produce(const void *buf, size_t count);
415         (void)uart0_rx_buffer_produce(&UartReceiveData, 1);
416     }
417 
418 	//KB_ESC chk is for cmd history, it's a special case here.
419 	if (UartReceiveData == KB_ASCII_ESC) {
420 		//4 Esc detection is only valid in the first stage of boot sequence (few seconds)
421 		if (shell_ctl.ExecuteEsc != _TRUE) {
422 			shell_ctl.ExecuteEsc = _TRUE;
423 			shell_ctl.EscSTS = 0;
424 		} else {
425 			//4 the input commands are valid only when the task is ready to execute commands
426 			if ((shell_ctl.BootRdy == 1)  ||(shell_ctl.shell_task_rdy == 1)) {
427 				if (shell_ctl.EscSTS==0) {
428 					shell_ctl.EscSTS = 1;
429 				}
430 			} else {
431 				shell_ctl.EscSTS = 0;
432 			}
433 		}
434 	} else if (shell_ctl.EscSTS==1) {
435 		if (UartReceiveData != KB_ASCII_LBRKT){
436 			shell_ctl.EscSTS = 0;
437 		} else {
438 			shell_ctl.EscSTS = 2;
439 		}
440 	} else {
441 		if (shell_ctl.EscSTS==2){
442 			shell_ctl.EscSTS = 0;
443 #ifdef CONFIG_UART_LOG_HISTORY
444 			if ((UartReceiveData=='A')|| UartReceiveData=='B'){
445 				shell_cmd_history(UartReceiveData,(UART_LOG_CTL *)&shell_ctl,1);
446 			}
447 #endif
448 		} else{
449 		}
450 	}
451 
452 	/* recv all data one time */
453 	if (shell_recv_all_data_onetime == 1) {
454 		if (LOGUART_Readable())
455 			goto recv_again;
456 	}
457 
458 	LOGUART_SetIMR(IrqEn);
459 	krhino_intrpt_exit();
460 }
461 
462 
463 SHELL_ROM_TEXT_SECTION _LONG_CALL_
shell_init_rom(u32 TBLSz,VOID * pTBL)464 VOID shell_init_rom(u32 TBLSz, VOID *pTBL)
465 {
466 	shell_buf.BufCount = 0;
467 	shell_array_init(&shell_buf.UARTLogBuf[0],UART_LOG_CMD_BUFLEN,'\0');
468 
469 	shell_ctl.NewIdx = 0;
470 	shell_ctl.SeeIdx = 0;
471 	shell_ctl.RevdNo = 0;
472 	shell_ctl.EscSTS = 0;
473 	shell_ctl.BootRdy = 0;
474 	shell_ctl.pTmpLogBuf = &shell_buf;
475 #ifdef CONFIG_UART_LOG_HISTORY
476 	shell_ctl.CRSTS = 0;
477 	shell_ctl.pHistoryBuf = &shell_history_cmd[0];
478 #endif
479 	shell_ctl.pfINPUT = (VOID *)&DiagPrintf;
480 
481 	if (TBLSz != 0) {
482 		shell_ctl.pCmdTbl = (PCOMMAND_TABLE) pTBL;
483 		shell_ctl.CmdTblSz = TBLSz;
484 	} else {
485 		void *PTable = NULL;
486 		u32 TblSize = cmd_rom_table(&PTable);
487 
488 		shell_ctl.pCmdTbl = (PCOMMAND_TABLE) PTable;
489 		shell_ctl.CmdTblSz = TblSize;
490 	}
491 	shell_ctl.shell_task_rdy = 0;
492 
493 	//executing boot sequence
494 	shell_ctl.ExecuteCmd = _FALSE;
495 	shell_ctl.ExecuteEsc = _FALSE;
496 
497 	CONSOLE_AMEBA();
498 }
499 
500 SHELL_ROM_TEXT_SECTION _LONG_CALL_
shell_task_rom(VOID * Data)501 VOID shell_task_rom(VOID *Data)
502 {
503 	/* To avoid gcc warnings */
504 	( void ) Data;
505 
506 	//4 Set this for UartLog check cmd history
507 #ifndef CONFIG_KERNEL
508 	shell_ctl.BootRdy = 1;
509 #endif
510 	do{
511 
512 		if ((shell_ctl.ExecuteCmd) == _TRUE) {
513 			shell_cmd_exec_rom((PUART_LOG_CTL)&shell_ctl);
514 			CONSOLE_AMEBA();
515 			shell_ctl.ExecuteCmd = _FALSE;
516 		}
517 	}while(1);
518 }
519 
520 SHELL_ROM_TEXT_SECTION _LONG_CALL_
shell_exit(u32 MaxWaitCount)521 static BOOLEAN shell_exit(u32 MaxWaitCount)
522 {
523 	u32 WaitCount = 0;
524 
525 	do{
526 		if (WaitCount > MaxWaitCount)
527 		{
528 			return _TRUE;// go back to the normal boot sequence
529 		}
530 
531 		DelayUs(100);
532 
533 		//        DBG_8195A("Wait %d\n",WaitCount);
534 		WaitCount++;
535 
536 		//4 there is a ESC key input in Boot Sequence check stage
537 		if (shell_ctl.ExecuteEsc == _TRUE)
538 		{
539 			CONSOLE_AMEBA();
540 
541 			shell_ctl.EscSTS = 0;
542 
543 			break;
544 		}
545 	}while(1);
546 
547 	return _FALSE;
548 
549 }
550 
551 
552 SHELL_ROM_TEXT_SECTION _LONG_CALL_
shell_rom(u32 MaxWaitCount)553 VOID shell_rom(u32 MaxWaitCount)
554 {
555 
556 	if (shell_exit(MaxWaitCount)) {
557 		//Go back to normal boot sequence
558 		return;
559 	}
560 
561 	/* rom cmd consol need this */
562 	LOG_MASK(LEVEL_ERROR, 0xFFFFFFFF);
563 
564 	shell_ctl.BootRdy = 1;
565 
566 	//4 Stay in console stage
567 	do{
568 		if ((shell_ctl.ExecuteCmd) == _TRUE) {
569 			shell_cmd_exec_rom((PUART_LOG_CTL)&shell_ctl);
570 			CONSOLE_AMEBA();
571 			shell_ctl.ExecuteCmd = _FALSE;
572 		}
573 	}while(1);
574 }
575 
576