printk uses a buffer in the cause that ms driver weren't ready.

This commit is contained in:
Hrimfaxi 2011-01-08 01:51:35 +08:00
parent 4c19ca986e
commit a4897b636c
2 changed files with 402 additions and 0 deletions

385
Common/printk.c Normal file
View File

@ -0,0 +1,385 @@
/*
*
* printk.c
*
* printk for bootbox
*
* support format:
* %c
* %s
* %[[0]n]x
* %[[0]n]X
* %[[0]n]d
*
*/
#include <pspsdk.h>
#include <pspkernel.h>
#include <pspdebug.h>
#include <pspdisplay.h>
#include <pspiofilemgr.h>
#include <stdarg.h>
#include <string.h>
struct pthread_mlock_t {
volatile unsigned long l;
unsigned int c;
int thread_id;
};
typedef struct pthread_mlock_t MLOCK_T;
static MLOCK_T lock;
extern void printk_lock(void);
extern void printk_unlock(void);
static int itostr(char *buf, int in_data, int base, int upper, int sign)
{
int res, len, i;
unsigned int data;
char *str;
if(base==10 && sign && in_data<0){
data = -in_data;
}else{
data = in_data;
}
str = buf;
do{
res = data%base;
data = data/base;
if(res<10){
res += '0';
}else{
if(upper){
res += 'A'-10;
}else{
res += 'a'-10;
}
}
*str++ = res;
}while(data);
len = str-buf;
/* reverse digital order */
for(i=0; i<len/2; i++){
res = buf[i];
buf[i] = buf[len-1-i];
buf[len-1-i] = res;
}
return len;
}
/*
* vsnprintf - Format a string and place it in a buffer
* @buf: The buffer to place the result into
* @size: The size of the buffer, including the trailing null space
* @fmt: The format string to use
* @args: Arguments for the format string
*/
#define OUT_C(c) \
if(str<end){ \
*str++ = (c); \
}
static char digital_buf[32];
int vsnprintf(char *buf, int size, char *fmt, va_list args)
{
char ch, *s, *str, *end, *sstr;
int zero_pad, left_adj, add_sign, field_width, sign;
int i, base, upper, len;
if(!buf || !fmt ||!size){
return 0;
}
str = buf;
end = buf+size;
while(*fmt){
if(*fmt!='%'){
OUT_C(*fmt++);
continue;
}
/* skip '%' */
sstr = fmt;
fmt++;
/* %% */
if(*fmt=='%'){
OUT_C(*fmt++);
continue;
}
/* get flag */
zero_pad = ' ';
left_adj = 0;
add_sign = 0;
while((ch=*fmt)){
if(*fmt=='0'){
zero_pad = '0';
}else if(*fmt=='-'){
left_adj = 1;
}else if(*fmt=='#'){
}else if(*fmt==' '){
if(add_sign!='+')
add_sign = ' ';
}else if(*fmt=='+'){
add_sign = '+';
}else{
break;
}
fmt++;
}
/* get field width: m.n */
field_width = 0;
/* get m */
while(*fmt && *fmt>'0' && *fmt<='9'){
field_width = field_width*10+(*fmt-'0');
fmt++;
}
if(*fmt && *fmt=='.'){
fmt++;
/* skip n */
while(*fmt && *fmt>'0' && *fmt<='9'){
fmt++;
}
}
/* get format char */
upper = 0;
base = 0;
sign = 0;
len = 0;
s = digital_buf;
while((ch=*fmt)){
fmt++;
switch(ch){
/* hexadecimal */
case 'p':
case 'X':
upper = 1;
case 'x':
base = 16;
break;
/* decimal */
case 'd':
case 'i':
sign = 1;
case 'u':
base = 10;
break;
/* octal */
case 'o':
base = 8;
break;
/* character */
case 'c':
digital_buf[0] = (unsigned char) va_arg(args, int);
len = 1;
break;
/* string */
case 's':
s = va_arg(args, char *);
if(!s) s = "<NUL>";
len = strlen(s);
break;
/* float format, skip it */
case 'e': case 'E': case 'f': case 'F': case 'g': case 'G': case 'a': case 'A':
va_arg(args, double);
s = NULL;
break;
/* length modifier */
case 'l': case 'L': case 'h': case 'j': case 'z': case 't':
/* skip it */
continue;
/* bad format */
default:
s = sstr;
len = fmt-sstr;
break;
}
break;
}
if(base){
i = va_arg(args, int);
if(base==10 && sign){
if(i<0){
add_sign = '-';
}
}else{
add_sign = 0;
}
len = itostr(digital_buf, i, base, upper, sign);
}else{
zero_pad = ' ';
add_sign = 0;
}
if(s){
if(len>=field_width){
field_width = len;
if(add_sign)
field_width++;
}
for(i=0; i<field_width; i++){
if(left_adj){
if(i<len){
OUT_C(*s++);
}else{
OUT_C(' ');
}
}else{
if(add_sign && (zero_pad=='0' || i==(field_width-len-1))){
OUT_C(add_sign);
add_sign = 0;
continue;
}
if(i<(field_width-len)){
OUT_C(zero_pad);
}else{
OUT_C(*s++);
}
}
}
}
}
OUT_C(0);
return str-buf;
}
static char printk_buf[128];
static char printk_memory_log[2048];
static char *printk_memory_log_ptr = printk_memory_log;
int printk(char *fmt, ...)
{
va_list args;
int printed_len;
int kout;
printk_lock();
va_start(args, fmt);
printed_len = vsnprintf(printk_buf, sizeof(printk_buf), fmt, args);
va_end(args);
printed_len--;
kout = sceKernelStdout();
sceIoWrite(kout, printk_buf, printed_len);
if ( 1 ) {
int fd;
fd = sceIoOpen("ms0:/LOG_SCTL.TXT", PSP_O_WRONLY | PSP_O_CREAT | PSP_O_APPEND, 0777);
if(fd < 0) {
fd = sceIoOpen("ef0:/LOG_SCTL.txt", PSP_O_WRONLY | PSP_O_CREAT | PSP_O_APPEND, 0777);
}
if (fd >= 0) {
if (printk_memory_log_ptr != printk_memory_log) {
// flush debug output
sceIoWrite(fd, printk_memory_log, printk_memory_log_ptr - printk_memory_log);
memset(printk_memory_log, 0, sizeof(printk_memory_log));
printk_memory_log_ptr = printk_memory_log;
}
sceIoWrite(fd, printk_buf, printed_len);
sceIoClose(fd);
} else {
// log to memory buf
if (printk_memory_log_ptr + printed_len < printk_memory_log + sizeof(printk_memory_log)) {
memcpy(printk_memory_log_ptr, printk_buf, printed_len);
printk_memory_log_ptr += printed_len;
}
}
}
sceKernelDelayThread(10000);
printk_unlock();
return printed_len;
}
static unsigned long my_InterlockedExchange(unsigned long volatile *dst, unsigned long exchange)
{
unsigned int flags = pspSdkDisableInterrupts();
unsigned long origvalue = *dst;
*dst = exchange;
pspSdkEnableInterrupts(flags);
return origvalue;
}
static inline int psp_mutex_lock(MLOCK_T *s)
{
for (;;) {
if (s->l != 0) {
if (s->thread_id == sceKernelGetThreadId()) {
++s->c;
return 0;
}
} else {
if (!my_InterlockedExchange(&s->l, 1)) {
s->thread_id = sceKernelGetThreadId();
s->c = 1;
return 0;
}
}
sceKernelDelayThread(1000);
}
return 0;
}
static inline void psp_mutex_unlock(MLOCK_T *s)
{
if (--s->c == 0) {
s->thread_id = 0;
my_InterlockedExchange(&s->l, 0);
}
}
void printk_lock(void)
{
psp_mutex_lock(&lock);
}
void printk_unlock(void)
{
psp_mutex_unlock(&lock);
}
int printk_init(void)
{
MLOCK_T *s = &lock;
s->l = 0;
s->c = 0;
s->thread_id = sceKernelGetThreadId();
return 0;
}

17
Common/printk.h Normal file
View File

@ -0,0 +1,17 @@
#ifndef PRINTK_H
#define PRINTK_H
#ifdef DEBUG
int printk_init(void);
int printk(char *fmt, ...)__attribute__((format (printf, 1, 2)));
int printk_lock(void);
int printk_unlock(void);
#else
#define printk_init()
#define printk(...)
#define printk_lock()
#define printk_unlock()
#endif
#endif