2005-04-16 15:20:36 -07:00
/*
2005-09-06 11:56:02 +10:00
* polling mode stateless debugging stuff , originally for NS16550 Serial Ports
2005-04-16 15:20:36 -07:00
*
* 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>
# include <linux/types.h>
2005-09-06 11:57:00 +10:00
# include <linux/sched.h>
2005-09-06 11:57:27 +10:00
# include <linux/console.h>
2006-06-07 12:06:20 +10:00
# include <linux/init.h>
2005-04-16 15:20:36 -07:00
# include <asm/processor.h>
2006-01-11 11:54:09 +11:00
# include <asm/udbg.h>
2005-04-16 15:20:36 -07:00
2005-11-23 17:57:25 +11:00
void ( * udbg_putc ) ( char c ) ;
2005-11-30 16:54:12 +11:00
int ( * udbg_getc ) ( void ) ;
2005-09-06 11:56:42 +10:00
int ( * udbg_getc_poll ) ( void ) ;
2006-01-11 11:54:09 +11:00
/*
* Early debugging facilities . You can enable _one_ of these via . config ,
* if you do so your kernel _will not boot_ on anything else . Be careful .
*/
void __init udbg_early_init ( void )
{
# if defined(CONFIG_PPC_EARLY_DEBUG_LPAR)
/* For LPAR machines that have an HVC console on vterm 0 */
udbg_init_debug_lpar ( ) ;
# elif defined(CONFIG_PPC_EARLY_DEBUG_G5)
/* For use on Apple G5 machines */
udbg_init_pmac_realmode ( ) ;
2006-06-23 18:20:16 +10:00
# elif defined(CONFIG_PPC_EARLY_DEBUG_RTAS_PANEL)
2006-01-11 11:54:09 +11:00
/* RTAS panel debug */
2006-06-23 18:20:16 +10:00
udbg_init_rtas_panel ( ) ;
# elif defined(CONFIG_PPC_EARLY_DEBUG_RTAS_CONSOLE)
/* RTAS console debug */
udbg_init_rtas_console ( ) ;
2006-01-11 11:54:09 +11:00
# elif defined(CONFIG_PPC_EARLY_DEBUG_MAPLE)
/* Maple real mode debug */
udbg_init_maple_realmode ( ) ;
# elif defined(CONFIG_PPC_EARLY_DEBUG_ISERIES)
/* For iSeries - hit Ctrl-x Ctrl-x to see the output */
udbg_init_iseries ( ) ;
# endif
}
2005-09-06 11:57:27 +10:00
/* udbg library, used by xmon et al */
2005-04-16 15:20:36 -07:00
void udbg_puts ( const char * s )
{
2005-09-06 11:56:42 +10:00
if ( udbg_putc ) {
2005-04-16 15:20:36 -07:00
char c ;
if ( s & & * s ! = ' \0 ' ) {
while ( ( c = * s + + ) ! = ' \0 ' )
2005-09-06 11:56:42 +10:00
udbg_putc ( c ) ;
2005-04-16 15:20:36 -07:00
}
}
#if 0
else {
printk ( " %s " , s ) ;
}
# endif
}
int udbg_write ( const char * s , int n )
{
int remain = n ;
char c ;
2005-09-06 11:56:42 +10:00
if ( ! udbg_putc )
2005-04-16 15:20:36 -07:00
return 0 ;
if ( s & & * s ! = ' \0 ' ) {
while ( ( ( c = * s + + ) ! = ' \0 ' ) & & ( remain - - > 0 ) ) {
2005-09-06 11:56:42 +10:00
udbg_putc ( c ) ;
2005-04-16 15:20:36 -07:00
}
}
return n - remain ;
}
int udbg_read ( char * buf , int buflen )
{
2005-11-30 16:54:12 +11:00
char * p = buf ;
int i , c ;
2005-04-16 15:20:36 -07:00
2005-09-06 11:56:42 +10:00
if ( ! udbg_getc )
2005-04-16 15:20:36 -07:00
return 0 ;
for ( i = 0 ; i < buflen ; + + i ) {
do {
2005-09-06 11:56:42 +10:00
c = udbg_getc ( ) ;
2005-11-30 16:54:12 +11:00
if ( c = = - 1 & & i = = 0 )
return - 1 ;
2005-04-16 15:20:36 -07:00
} while ( c = = 0x11 | | c = = 0x13 ) ;
2005-11-30 16:54:12 +11:00
if ( c = = 0 | | c = = - 1 )
2005-04-16 15:20:36 -07:00
break ;
* p + + = c ;
}
return i ;
}
# define UDBG_BUFSIZE 256
void udbg_printf ( const char * fmt , . . . )
{
2005-11-23 17:57:25 +11:00
char buf [ UDBG_BUFSIZE ] ;
2005-04-16 15:20:36 -07:00
va_list args ;
va_start ( args , fmt ) ;
vsnprintf ( buf , UDBG_BUFSIZE , fmt , args ) ;
udbg_puts ( buf ) ;
va_end ( args ) ;
}
2005-12-20 16:37:07 -06:00
void __init udbg_progress ( char * s , unsigned short hex )
{
udbg_puts ( s ) ;
udbg_puts ( " \n " ) ;
}
2005-09-06 11:57:27 +10:00
/*
* 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 ,
2005-11-23 17:56:06 +11:00
. flags = CON_PRINTBUFFER | CON_ENABLED ,
2005-09-06 11:57:27 +10:00
. index = - 1 ,
} ;
2005-09-07 19:52:38 +10:00
static int early_console_initialized ;
2005-09-06 11:57:27 +10:00
void __init disable_early_printk ( void )
{
2005-09-07 19:52:38 +10:00
if ( ! early_console_initialized )
return ;
2006-06-07 12:06:20 +10:00
if ( strstr ( saved_command_line , " udbg-immortal " ) ) {
printk ( KERN_INFO " early console immortal ! \n " ) ;
return ;
}
2005-09-06 11:57:27 +10:00
unregister_console ( & udbg_console ) ;
2005-09-07 19:52:38 +10:00
early_console_initialized = 0 ;
2005-09-06 11:57:27 +10:00
}
/* called by setup_system */
void register_early_udbg_console ( void )
{
2005-11-23 17:57:25 +11:00
if ( early_console_initialized )
return ;
2005-09-07 19:52:38 +10:00
early_console_initialized = 1 ;
2005-09-06 11:57:27 +10:00
register_console ( & udbg_console ) ;
}
#if 0 /* if you want to use this as a regular output console */
console_initcall ( register_udbg_console ) ;
# endif