OSHW-DEIMOS/SOFTWARE/A64-TERES/linux-a64/drivers/soc/allwinner/pm/mem_printk.c
Dimitar Gamishev f9b0e7a283 linux
2017-10-13 14:07:04 +03:00

477 lines
8.3 KiB
C
Executable File

/**
* common.c - common operations
* date: 2012-2-13 8:42:56
* author: Aaron<leafy.myeh@allwinnertech.com>
* history: V0.1
*/
#include "pm_i.h"
static __s32 print_align(char *string, __s32 len, __s32 align);
#define NUM_TYPE long long
#define ZEROPAD 1 /* pad with zero */
#define SIGN 2 /* unsigned/signed long */
#define PLUS 4 /* show plus */
#define SPACE 8 /* space if plus */
#define LEFT 16 /* left justified */
#define SMALL 32 /* Must be 32 == 0x20 */
#define SPECIAL 64 /* 0x */
#define is_digit(c) ((c) >= '0' && (c) <= '9')
/* Basic string functions */
/*
s t r l e n
returns number of characters in s (not including terminating null character)
*/
size_t strlen(const char *s)
{
const char *sc;
for (sc = s; *sc != '\0'; ++sc)
{
/* nothing */
;
}
return sc - s;
}
/*
s t r c p y
Copy 'src' to 'dest'. Strings may not overlap.
*/
char *strcpy(char *dest, const char *src)
{
char *tmp = dest;
while ((*dest++ = *src++) != '\0')
{
/* nothing */
;
}
return tmp;
}
char *strncpy(char *dest, const char *src, size_t count)
{
char *tmp = dest;
while (count)
{
if ((*tmp = *src) != 0)
{
src++;
}
tmp++;
count--;
}
return dest;
}
char *strcat(char *dest, const char *src)
{
char *tmp = dest;
while (*dest)
{
dest++;
}
while ((*dest++ = *src++) != '\0')
{
;
}
return tmp;
}
char *strncat(char *dest, const char *src, size_t count)
{
char *tmp = dest;
if (count)
{
while (*dest)
{
dest++;
}
while ((*dest++ = *src++) != 0)
{
if (--count == 0)
{
*dest = '\0';
break;
}
}
}
return tmp;
}
int strcmp(const char *cs, const char *ct)
{
unsigned char c1, c2;
while (1)
{
c1 = *cs++;
c2 = *ct++;
if (c1 != c2)
{
return c1 < c2 ? -1 : 1;
}
if (!c1)
{
break;
}
}
return 0;
}
int strncmp(const char *cs, const char *ct, size_t count)
{
unsigned char c1, c2;
while (count) {
c1 = *cs++;
c2 = *ct++;
if (c1 != c2)
return c1 < c2 ? -1 : 1;
if (!c1)
break;
count--;
}
return 0;
}
static int skip_atoi(const char **s)
{
int i=0;
while (is_digit(**s))
i = i*10 + *((*s)++) - '0';
return i;
}
static char *itoa(int value, char *string, int radix)
{
char stack[16];
int negative = 0; //defualt is positive value
int i;
int j;
char digit_string[] = "0123456789ABCDEF";
if(value == 0)
{
//zero
string[0] = '0';
string[1] = '\0';
return string;
}
if(value < 0)
{
//'value' is negative, convert to postive first
negative = 1;
value = -value ;
}
for(i = 0; value > 0; ++i)
{
// characters in reverse order are put in 'stack'.
stack[i] = digit_string[value % radix];
value /= radix;
}
//restore reversed order result to user string
j = 0;
if(negative)
{
//add sign at first charset.
string[j++] = '-';
}
for(--i; i >= 0; --i, ++j)
{
string[j] = stack[i];
}
//must end with '\0'.
string[j] = '\0';
return string;
}
static char *utoa(unsigned int value, char *string, int radix)
{
char stack[16];
int i;
int j;
char digit_string[] = "0123456789ABCDEF";
if(value == 0)
{
//zero
string[0] = '0';
string[1] = '\0';
return string;
}
for(i = 0; value > 0; ++i)
{
// characters in reverse order are put in 'stack'.
stack[i] = digit_string[value % radix];
value /= radix;
}
//restore reversed order result to user string
for(--i, j = 0; i >= 0; --i, ++j)
{
string[j] = stack[i];
}
//must end with '\0'.
string[j] = '\0';
return string;
}
/*
*********************************************************************************************************
* FORMATTED PRINTF
*
* Description: print out a formatted string, similar to ANSI-C function printf().
* This function can support and only support the following conversion specifiers:
* %d signed decimal integer.
* %u unsigned decimal integer.
* %x unsigned hexadecimal integer, using hex digits 0x.
* %c single character.
* %s character string.
*
* Arguments : format : format control.
* ... : arguments.
*
* Returns : the number of characters printed out.
*
* Note : the usage refer to ANSI-C function printf().
*********************************************************************************************************
*/
static char debugger_buffer[DEBUG_BUFFER_SIZE];
__s32 printk(const char *format, ...)
{
va_list args;
char string[16]; //align by cpu word
char *pdest;
char *psrc;
__s32 align;
__s32 len = 0;
//dump current timestemp
//print_current_time();
pdest = debugger_buffer;
va_start(args, format);
while(*format)
{
if(*format == '%')
{
++format;
if (('0' < (*format)) && ((*format) <= '9'))
{
//we just suport wide from 1 to 9.
align = *format - '0';
++format;
}
else
{
align = 0;
}
switch(*format)
{
case 'd':
{
//int
itoa(va_arg(args, int), string, 10);
len = strlen(string);
len += print_align(string, len, align);
strcpy(pdest, string);
pdest += len;
break;
}
case 'x':
case 'p':
{
//hex
utoa(va_arg(args, int), string, 16);
len = strlen(string);
len += print_align(string, len, align);
strcpy(pdest, string);
pdest += len;
break;
}
case 'u':
{
//unsigned int
utoa(va_arg(args, int), string, 10);
len = strlen(string);
len += print_align(string, len, align);
strcpy(pdest, string);
pdest += len;
break;
}
case 'c':
{
//charset, aligned by cpu word
*pdest = (char)va_arg(args, int);
break;
}
case 's':
{
//string
psrc = va_arg(args, char *);
strcpy(pdest, psrc);
pdest += strlen(psrc);
break;
}
default :
{
//no-conversion
*pdest++ = '%';
*pdest++ = *format;
}
}
}
else
{
*pdest++ = *format;
}
//parse next token
++format;
}
va_end(args);
//must end with '\0'
*pdest = '\0';
pdest++;
serial_puts(debugger_buffer);
return (pdest - debugger_buffer);
}
static __s32 print_align(char *string, __s32 len, __s32 align)
{
//fill with space ' ' when align request,
//the max align length is 16 byte.
char fill_ch[] = " ";
if (len < align)
{
//fill at right
strncat(string, fill_ch, align - len);
return align - len;
}
//not fill anything
return 0;
}
__s32 printk_nommu(const char *format, ...)
{
va_list args;
char string[16]; //align by cpu word
char *pdest;
char *psrc;
__s32 align;
__s32 len = 0;
//dump current timestemp
//print_current_time();
pdest = debugger_buffer;
va_start(args, format);
while(*format)
{
if(*format == '%')
{
++format;
if (('0' < (*format)) && ((*format) <= '9'))
{
//we just suport wide from 1 to 9.
align = *format - '0';
++format;
}
else
{
align = 0;
}
switch(*format)
{
case 'd':
{
//int
itoa(va_arg(args, int), string, 10);
len = strlen(string);
len += print_align(string, len, align);
strcpy(pdest, string);
pdest += len;
break;
}
case 'x':
case 'p':
{
//hex
utoa(va_arg(args, int), string, 16);
len = strlen(string);
len += print_align(string, len, align);
strcpy(pdest, string);
pdest += len;
break;
}
case 'u':
{
//unsigned int
utoa(va_arg(args, int), string, 10);
len = strlen(string);
len += print_align(string, len, align);
strcpy(pdest, string);
pdest += len;
break;
}
case 'c':
{
//charset, aligned by cpu word
*pdest = (char)va_arg(args, int);
break;
}
case 's':
{
//string
psrc = va_arg(args, char *);
strcpy(pdest, psrc);
pdest += strlen(psrc);
break;
}
default :
{
//no-conversion
*pdest++ = '%';
*pdest++ = *format;
}
}
}
else
{
*pdest++ = *format;
}
//parse next token
++format;
}
va_end(args);
//must end with '\0'
*pdest = '\0';
pdest++;
serial_puts_nommu(debugger_buffer);
return (pdest - debugger_buffer);
}