| /* |
| * (C) Copyright Marvell Semiconductors,Inc 2006 All rightes reserved |
| */ |
| |
| #include "util.h" |
| #include "ctypes.h" |
| #include "string.h" |
| #include "debug.h" |
| #include "apb_perf_base.h" |
| #include "lgpl_printf.h" |
| |
| |
| /* |
| * heap start point |
| */ |
| static void * malloc_base; |
| |
| void * UtilMemSet(void *s, int c, int n) |
| { |
| |
| unsigned char * char_ptr = s; |
| unsigned int * int_ptr = s; |
| int remainer; |
| |
| if((remainer = ((int)s & 3)) != 0) { |
| while (remainer-- > 0) { |
| *char_ptr++ = (unsigned char)c; |
| n--; |
| } |
| int_ptr = (unsigned int *)char_ptr; |
| remainer = n & 3; |
| } |
| |
| n >>= 2; |
| while (n-- > 0) { |
| *int_ptr++ = (unsigned int)c; |
| } |
| |
| if (remainer != 0) { |
| unsigned int temp = *int_ptr; |
| unsigned char * temp_p = (unsigned char *)&temp; |
| while (remainer-- > 0) { |
| *temp_p++ = (unsigned char)c; |
| } |
| *int_ptr = temp; |
| } |
| return(s); |
| } |
| |
| void * UtilMemCpy(void *s1, const void *s2, int n) |
| { |
| |
| unsigned int * dst = s1; |
| const unsigned int * src = s2; |
| int remainer = n & 3; |
| |
| if (((unsigned int)s1 & 3) || ((unsigned int)s2 & 3)) { |
| unsigned char * dst_char = s1; |
| const unsigned char * src_char = s2; |
| |
| while (n-- > 0) { |
| *dst_char++ = *src_char++; |
| } |
| return s1; |
| } |
| |
| n >>= 2; |
| while (n-- > 0) { |
| *dst++ = *src++; |
| } |
| |
| if (remainer != 0) { |
| unsigned int temp = *dst; |
| unsigned char * temp_p = (unsigned char *)&temp; |
| const unsigned char * src_c = (const unsigned char *)src; |
| while (remainer-- > 0) { |
| *temp_p++ = (unsigned char)*src_c++; |
| } |
| *dst = temp; |
| } |
| |
| return(s1); |
| } |
| |
| int UtilMemCmp(const void *s1, const void *s2, int n) |
| { |
| |
| int i = 0; |
| const unsigned char * ss1 = s1; |
| const unsigned char * ss2 = s2; |
| |
| for ( ; i < n; i++) { |
| if (ss1[i] > ss2[i]) { |
| return(i + 1); |
| } |
| else if (ss1[i] < ss2[i]) { |
| return(-i - 1); |
| } |
| } |
| |
| return 0; |
| } |
| |
| void * UtilMemAllocZ(int size) |
| { |
| if (size > 0) { |
| unsigned long malloc_align = (((unsigned long) malloc_base + 31) >> 5) << 5; |
| void * ptr = (void *) malloc_align; |
| |
| UtilMemSet(ptr, 0, size); |
| malloc_base = (void *) malloc_align + size; |
| return(ptr); |
| } |
| return(0); |
| } |
| |
| void * UtilMemAlloc(int size) |
| { |
| if (size > 0) { |
| unsigned long malloc_align = (((unsigned long) malloc_base + 31) >> 5) << 5; |
| void * ptr = (void *) malloc_align; |
| |
| if( (void *)(malloc_align + size) > __user_read_heap_top() ) |
| return 0; |
| malloc_base = (void *)(malloc_align + size); |
| return(ptr); |
| } |
| return(0); |
| } |
| |
| void UtilMemReset(void) |
| { |
| malloc_base = __user_read_heap_bottom(); |
| } |
| |
| |
| #define DBG_MEM (0x3000000) |
| #define DBG_PORT_BASE (SM_APB_UART0_BASE) |
| #define PUT_CHAR(ch) BFM_HOST_Bus_Write32((DBG_PORT_BASE+0x00), (UNSG32)ch) |
| #define put_char PUT_CHAR |
| |
| #define MAX_HISBUF_ENTRY 16 |
| static char his_buf[MAX_HISBUF_ENTRY][80]; // for Historical commands support |
| static SIGN32 his_mode=0; |
| SIGN32 his_next_idx=0; |
| SIGN32 his_cur_idx=0; |
| SIGN32 his_cmd_cnt=0; |
| SIGN32 pre_his_cmd_length; |
| |
| static void * malloc_base; |
| |
| unsigned char GET_CHAR() |
| { |
| UNSG32 data32; |
| unsigned char data8; |
| BFM_HOST_Bus_Read32((DBG_PORT_BASE+0x00), &data32); |
| |
| data8=data32&0xFF; |
| return data8; |
| |
| } |
| |
| //////////////////////////////////////////////////////////// |
| // dbg port (uart) driver |
| SIGN32 dbg_port_tx_ready() |
| { |
| UNSG32 status=0; |
| do |
| { |
| BFM_HOST_Bus_Read32((DBG_PORT_BASE+0x7c),&status); |
| } while ((status&0x03)!=0x02); |
| // add extra protection below |
| do |
| { |
| BFM_HOST_Bus_Read32((DBG_PORT_BASE+0x80),&status); |
| } while (status>2); //delay control |
| return 1; |
| } |
| |
| ///////////////////////////////////////////////////////////////////////// |
| // |
| // showDbgPrompt() - Used by the debugger. Displays the appropriate |
| // debugger prompt. |
| // |
| ///////////////////////////////////////////////////////////////////////// |
| void showDbgPrompt(char* prompt) |
| { |
| lgpl_printf("\n\n%s", prompt); |
| } |
| |
| |
| SIGN32 dbg_port_rx_ready() |
| { |
| UNSG32 read; |
| BFM_HOST_Bus_Read32((DBG_PORT_BASE+0x7c),&read); // status |
| if(read&0x08) |
| { |
| BFM_HOST_Bus_Read32((DBG_PORT_BASE+0x84),&read); // RFL |
| if (read>0) |
| return 1; |
| } |
| return 0; |
| } |
| |
| void dbg_port_print( char* str) |
| { |
| char ch; |
| SIGN32 i; |
| SIGN32 len=strlen(str); |
| dbg_port_tx_ready(); |
| for (i=0;i<len;i++) |
| { |
| ch=str[i]; |
| put_char(ch); |
| if (ch=='\n') |
| { |
| ch='\r'; |
| put_char(ch); |
| } |
| //extra delay |
| i=i; |
| len=len; |
| ch=str[i]; |
| } |
| } |
| |
| |
| ////////////////////////////////////////////////////// |
| // read command via UART (RS232) |
| #define CR_CHAR 13 |
| #define LF_CHAR 10 |
| #define BS_CHAR 8 |
| #define UP_CHAR '.' |
| #define DIR1_CHAR 0x1B |
| #define DIR2_CHAR '[' |
| #define UP3_CHAR 'A' |
| #define DOWN3_CHAR 'B' |
| |
| int getline(char *pCmd) |
| { |
| unsigned char ch; |
| SIGN32 i; |
| #if 0 |
| SIGN32 comment; |
| #endif |
| unsigned char arrow = 0; |
| int input_cmd_line_length = 0 ; |
| |
| |
| for (i = 0; i < CMD_LINE_BUFFER_SIZE; i++) |
| pCmd[i] = 0; |
| |
| i = 0; |
| input_cmd_line_length = 0 ; |
| while (1) |
| { |
| while (dbg_port_rx_ready() == 0); |
| ch = GET_CHAR(); |
| arrow += 2; |
| input_cmd_line_length++ ; |
| if(input_cmd_line_length>CMD_LINE_BUFFER_SIZE){ |
| lgpl_printf("cmd line overflow, please input the command line again\n") ; |
| return 1 ; |
| } |
| |
| switch (ch) |
| { |
| case CR_CHAR: |
| case LF_CHAR: |
| case '\0': |
| pCmd[i] = '\0'; |
| #if 0 |
| comment = 0; |
| if (his_mode == 0 && strlen(pCmd)) |
| { // only store new command that is not null |
| memset(his_buf[his_cur_idx], 0, 80); // clear buf |
| memcpy(his_buf[his_cur_idx], pCmd, strlen(pCmd)); |
| if (his_cur_idx < MAX_HISBUF_ENTRY - 1) |
| { |
| his_next_idx = his_cur_idx; |
| his_cur_idx++; |
| } |
| else |
| { |
| his_next_idx = MAX_HISBUF_ENTRY - 1; |
| his_cur_idx = 0; |
| } |
| his_cmd_cnt = (his_cmd_cnt < MAX_HISBUF_ENTRY) ? (his_cmd_cnt + 1) : MAX_HISBUF_ENTRY; |
| } |
| his_mode = 0; |
| #endif |
| return 0 ; |
| |
| #if 0 |
| case ';': |
| case '/': |
| comment = 1; |
| break; |
| |
| case BS_CHAR: |
| i--; |
| i--; |
| PUT_CHAR(ch); |
| PUT_CHAR(' '); |
| PUT_CHAR(ch); |
| his_mode = 0; // modify historical command |
| arrow = 0; |
| break; |
| #endif |
| default: |
| pCmd[i] = ch ; |
| // PUT_CHAR(ch); |
| PUT_CHAR('*'); |
| #if 0 |
| if (comment == 0) |
| { |
| pCmd[i] = ch; |
| if (ch == DIR1_CHAR) |
| arrow = 1; |
| else if (ch == DIR2_CHAR && arrow == 3) |
| arrow = arrow; |
| else if (ch == UP3_CHAR && arrow == 5) |
| { |
| arrow = 0; |
| PUT_CHAR(DIR1_CHAR); |
| PUT_CHAR(DIR2_CHAR); |
| PUT_CHAR(DOWN3_CHAR); |
| i = previous_cmd(pCmd, i, 0); |
| } |
| else if (ch == DOWN3_CHAR && arrow == 5) |
| { |
| arrow = 0; |
| i = next_cmd(pCmd, i); |
| } |
| else |
| { |
| his_mode = 0; // modify history command |
| arrow = 0; |
| } |
| } |
| #endif |
| break; |
| } |
| i++; |
| } |
| } |
| |
| int previous_cmd(char *pCmd, int cur_cmd_length, unsigned int loop) |
| { |
| int i, j; |
| int erase; |
| |
| if (his_cmd_cnt == 0) |
| return (cur_cmd_length - 3); |
| |
| if (his_mode == 0) |
| { |
| his_mode = 1; |
| } |
| else |
| { |
| if (loop == 0) |
| { |
| if (his_next_idx == his_cur_idx + 1) |
| return (cur_cmd_length - 3); |
| |
| if ((his_next_idx == 0) && (his_cur_idx == his_cmd_cnt)) |
| return (cur_cmd_length - 3); |
| } |
| |
| if (his_next_idx == 0) |
| his_next_idx = his_cmd_cnt - 1; |
| else |
| his_next_idx--; |
| } |
| |
| // need to clear line, move cursor, and print prompt again |
| erase = strlen(PROMPT) + (pre_his_cmd_length > cur_cmd_length ? pre_his_cmd_length : cur_cmd_length); |
| put_char('\r'); |
| for (j = 0; j <= erase ; j++) |
| { |
| put_char(' '); |
| } |
| put_char('\r'); // back to beginning of line |
| dbg_port_print(PROMPT); // show prompt |
| |
| dbg_port_print(his_buf[his_next_idx]); |
| |
| memcpy(pCmd, his_buf[his_next_idx], strlen(his_buf[his_next_idx])); |
| i = strlen(his_buf[his_next_idx]) - 1; |
| pre_his_cmd_length = i; // record the his command length |
| |
| return i; |
| } |
| |
| int next_cmd(char *pCmd, int cur_cmd_length) |
| { |
| int i, j; |
| int erase; |
| |
| his_mode = 2; |
| if (his_cur_idx == his_next_idx + 1) |
| return (cur_cmd_length - 3); |
| |
| if ((his_cur_idx == 0) && (his_next_idx == his_cmd_cnt)) |
| return (cur_cmd_length - 3); |
| |
| if (his_next_idx == his_cmd_cnt - 1) |
| his_next_idx = 0; |
| else |
| his_next_idx++; |
| |
| // need to clear line, move cursor, and print prompt again |
| erase = strlen(PROMPT) + (pre_his_cmd_length > cur_cmd_length ? pre_his_cmd_length : cur_cmd_length); |
| put_char('\r'); |
| for (j = 0; j <= erase; j++) |
| { |
| put_char(' '); |
| } |
| put_char('\r'); // back to beginning of line |
| dbg_port_print(PROMPT); // show prompt |
| |
| dbg_port_print(his_buf[his_next_idx]); |
| |
| memcpy(pCmd, his_buf[his_next_idx], strlen(his_buf[his_next_idx])); |
| i = strlen(his_buf[his_next_idx]) - 1; |
| pre_his_cmd_length = i; // record the his command length |
| |
| return i; |
| } |
| |
| ///////////////////////////////////////////////////////////////////////// |
| // |
| // skipSpace() - Used by the debugger. Skips non-text characters at |
| // the beginning of a string |
| // |
| ///////////////////////////////////////////////////////////////////////// |
| void skipSpace ( char **inStr ) |
| { |
| char *s = *inStr; |
| |
| while (( *s == ' ' ) || ( *s == '\t' ) || ( *s == '\r' ) || ( *s == '\n' )) |
| s++; |
| |
| *inStr = s; |
| } |
| |
| |
| ///////////////////////////////////////////////////////////////////////// |
| // |
| // getTokenLength() - Used by the debugger. Gets the length of the |
| // next token in a string |
| // |
| ///////////////////////////////////////////////////////////////////////// |
| SIGN32 getTokenLength (char *s ) |
| { |
| SIGN32 index; |
| char x; |
| |
| for ( index = 0; s[ index] != 0; index++ ) |
| { |
| x = s[ index]; |
| if (( x == ' ' ) || ( x == '\t' ) || ( x == '\r' ) || ( x == '\n' )) |
| break; |
| } |
| |
| return( index ); |
| } |
| |
| ///////////////////////////////////////////////////////////////////////// |
| // |
| // getIntToken() - Used by the debugger Gets the next token from a string |
| // |
| ///////////////////////////////////////////////////////////////////////// |
| char* getIntToken ( char *inStr, UNSG32 *outVal ) |
| { |
| SIGN32 iSum = 0; |
| char c; |
| char *thisStr = inStr; |
| SIGN32 bPositive = 1; |
| // If first character is ';', we have a comment, so |
| // get out of here. |
| if ( *thisStr == ';' ) |
| return thisStr; |
| |
| // Process decimal characters |
| // a negative number? |
| if ( *thisStr == '-' ) |
| { |
| bPositive =0; |
| thisStr ++; |
| } |
| |
| while ( *thisStr ) |
| { |
| c = *thisStr; |
| |
| // Check for valid digits. |
| if ( !( c >= '0' && c <= '9' ) ) |
| break; |
| |
| // ASCII to decimal conversion |
| iSum = iSum * 10 + ( c - '0' ); |
| |
| thisStr ++; |
| } |
| |
| // make it negative |
| if ( !bPositive ) |
| iSum = -1 * iSum; |
| |
| // Return updated pointer and decoded value. |
| *outVal = iSum; |
| return thisStr; |
| } |
| |
| ///////////////////////////////////////////////////////////////////////// |
| // |
| // getSignedIntToken() - Used by the debugger Gets the next token from a string |
| // |
| ///////////////////////////////////////////////////////////////////////// |
| char* getSignedIntToken ( char *inStr, SIGN32 *outVal ) |
| { |
| SIGN32 iSum = 0; |
| char c; |
| char *thisStr = inStr; |
| SIGN32 bPositive = 1; |
| // If first character is ';', we have a comment, so |
| // get out of here. |
| if ( *thisStr == ';' ) |
| return thisStr; |
| |
| // Process decimal characters |
| // a negative number? |
| if ( *thisStr == '-' ) |
| { |
| bPositive =0; |
| thisStr ++; |
| } |
| |
| while ( *thisStr ) |
| { |
| c = *thisStr; |
| |
| // Check for valid digits. |
| if ( !( c >= '0' && c <= '9' ) ) |
| break; |
| |
| // ASCII to decimal conversion |
| iSum = iSum * 10 + ( c - '0' ); |
| |
| thisStr ++; |
| } |
| |
| // make it negative |
| if ( !bPositive ) |
| iSum = -1 * iSum; |
| |
| // Return updated pointer and decoded value. |
| *outVal = iSum; |
| return thisStr; |
| } |
| |
| ///////////////////////////////////////////////////////////////////////// |
| // |
| // getHexToken() - Used by the debugger Gets the next token from a string |
| // |
| ///////////////////////////////////////////////////////////////////////// |
| char* getHexToken ( char *inStr, UNSG32 *outVal ) |
| { |
| UNSG32 thisVal, tVal; |
| char x; |
| char *thisStr = inStr; |
| |
| thisVal = 0; |
| |
| // If first character is ';', we have a comment, so |
| // get out of here. |
| |
| if ( *thisStr == ';' ) |
| return( thisStr ); |
| |
| // Process hex characters. |
| |
| while ( *thisStr ) |
| { |
| // Do uppercase conversion if necessary. |
| |
| x = *thisStr; |
| if (( x >= 'a') && ( x <= 'f')) |
| x &= ~0x20; |
| |
| // Check for valid digits. |
| |
| if ( !((( x >= '0') && (x <= '9')) || (( x >= 'A') && ( x <= 'F')))) |
| break; |
| |
| // Hex ASCII to binary conversion. |
| |
| tVal = x - '0'; |
| if ( tVal > 9 ) |
| tVal -= 7; |
| |
| thisVal = (thisVal * 16) + tVal; |
| |
| thisStr++; |
| } |
| |
| // Return updated pointer and decoded value. |
| |
| *outVal = thisVal; |
| return( thisStr ); |
| } |
| |
| ///////////////////////////////////////////////////////////////////////// |
| // |
| // getToken() - Used by the debugger Gets the next token from a string |
| // |
| ///////////////////////////////////////////////////////////////////////// |
| char* getToken ( char *inStr, char **outVal ) |
| { |
| char *thisStr = inStr; |
| |
| // If first character is ';', we have a comment, so |
| // get out of here. |
| |
| if ( *thisStr == ';' ) |
| return( thisStr ); |
| |
| while ( *thisStr != ' ' && *thisStr != '\t' && *thisStr != '\0' ) |
| { |
| thisStr++; |
| } |
| |
| if ( *thisStr != '\0' ) |
| { |
| *thisStr = '\0'; |
| thisStr ++; |
| } |
| |
| *outVal = inStr; |
| return( thisStr ); |
| } |
| |
| |
| // Qingwei Huang added for google's toolchain |
| int raise(int i) |
| { |
| (void)i; |
| return 0; |
| } |