udbg.c 3.3 KB
Newer Older
L
Linus Torvalds 已提交
1
/*
2
 * polling mode stateless debugging stuff, originally for NS16550 Serial Ports
L
Linus Torvalds 已提交
3 4 5 6 7 8 9 10 11 12 13 14 15
 *
 * c 2001 PPC 64 Team, IBM Corp
 *
 *      This program is free software; you can redistribute it and/or
 *      modify it under the terms of the GNU General Public License
 *      as published by the Free Software Foundation; either version
 *      2 of the License, or (at your option) any later version.
 */

#include <stdarg.h>
#define WANT_PPCDBG_TAB /* Only defined here */
#include <linux/config.h>
#include <linux/types.h>
16
#include <linux/sched.h>
17
#include <linux/console.h>
L
Linus Torvalds 已提交
18 19 20
#include <asm/ppcdebug.h>
#include <asm/processor.h>

21 22 23 24
void (*udbg_putc)(unsigned char c);
unsigned char (*udbg_getc)(void);
int (*udbg_getc_poll)(void);

25
/* udbg library, used by xmon et al */
L
Linus Torvalds 已提交
26 27
void udbg_puts(const char *s)
{
28
	if (udbg_putc) {
L
Linus Torvalds 已提交
29 30 31 32
		char c;

		if (s && *s != '\0') {
			while ((c = *s++) != '\0')
33
				udbg_putc(c);
L
Linus Torvalds 已提交
34 35 36 37 38 39 40 41 42 43 44 45 46 47
		}
	}
#if 0
	else {
		printk("%s", s);
	}
#endif
}

int udbg_write(const char *s, int n)
{
	int remain = n;
	char c;

48
	if (!udbg_putc)
L
Linus Torvalds 已提交
49 50 51 52
		return 0;

	if (s && *s != '\0') {
		while (((c = *s++) != '\0') && (remain-- > 0)) {
53
			udbg_putc(c);
L
Linus Torvalds 已提交
54 55 56 57 58 59 60 61 62 63 64
		}
	}

	return n - remain;
}

int udbg_read(char *buf, int buflen)
{
	char c, *p = buf;
	int i;

65
	if (!udbg_getc)
L
Linus Torvalds 已提交
66 67 68 69
		return 0;

	for (i = 0; i < buflen; ++i) {
		do {
70
			c = udbg_getc();
L
Linus Torvalds 已提交
71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91
		} while (c == 0x11 || c == 0x13);
		if (c == 0)
			break;
		*p++ = c;
	}

	return i;
}

#define UDBG_BUFSIZE 256
void udbg_printf(const char *fmt, ...)
{
	unsigned char buf[UDBG_BUFSIZE];
	va_list args;

	va_start(args, fmt);
	vsnprintf(buf, UDBG_BUFSIZE, fmt, args);
	udbg_puts(buf);
	va_end(args);
}

92 93 94 95
/* PPCDBG stuff */

u64 ppc64_debug_switch;

L
Linus Torvalds 已提交
96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134
/* Special print used by PPCDBG() macro */
void udbg_ppcdbg(unsigned long debug_flags, const char *fmt, ...)
{
	unsigned long active_debugs = debug_flags & ppc64_debug_switch;

	if (active_debugs) {
		va_list ap;
		unsigned char buf[UDBG_BUFSIZE];
		unsigned long i, len = 0;

		for (i=0; i < PPCDBG_NUM_FLAGS; i++) {
			if (((1U << i) & active_debugs) && 
			    trace_names[i]) {
				len += strlen(trace_names[i]); 
				udbg_puts(trace_names[i]);
				break;
			}
		}

		snprintf(buf, UDBG_BUFSIZE, " [%s]: ", current->comm);
		len += strlen(buf); 
		udbg_puts(buf);

		while (len < 18) {
			udbg_puts(" ");
			len++;
		}

		va_start(ap, fmt);
		vsnprintf(buf, UDBG_BUFSIZE, fmt, ap);
		udbg_puts(buf);
		va_end(ap);
	}
}

unsigned long udbg_ifdebug(unsigned long flags)
{
	return (flags & ppc64_debug_switch);
}
135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174

/*
 * Initialize the PPCDBG state.  Called before relocation has been enabled.
 */
void __init ppcdbg_initialize(void)
{
	ppc64_debug_switch = PPC_DEBUG_DEFAULT; /* | PPCDBG_BUSWALK | */
	/* PPCDBG_PHBINIT | PPCDBG_MM | PPCDBG_MMINIT | PPCDBG_TCEINIT | PPCDBG_TCE */;
}

/*
 * Early boot console based on udbg
 */
static void udbg_console_write(struct console *con, const char *s,
		unsigned int n)
{
	udbg_write(s, n);
}

static struct console udbg_console = {
	.name	= "udbg",
	.write	= udbg_console_write,
	.flags	= CON_PRINTBUFFER,
	.index	= -1,
};

void __init disable_early_printk(void)
{
	unregister_console(&udbg_console);
}

/* called by setup_system */
void register_early_udbg_console(void)
{
	register_console(&udbg_console);
}

#if 0   /* if you want to use this as a regular output console */
console_initcall(register_udbg_console);
#endif