oleavr-rgl-a500-mini-linux-.../drivers/soc/allwinner/pm/mem_printk.c
Ole André Vadla Ravnås 169c65d57e Initial commit
2022-05-07 01:01:45 +02:00

448 lines
8.4 KiB
C

/*
* Copyright (c) 2007-2017 Allwinnertech Co., Ltd.
*
* This software is licensed under the terms of the GNU General Public
* License version 2, as published by the Free Software Foundation, and
* may be copied, distributed, and modified under those terms.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
*/
/**
* 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) {
*tmp = *src;
if ((*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;
}