2005-04-17 02:20:36 +04:00
/*
2005-09-06 05:56:02 +04:00
* polling mode stateless debugging stuff , originally for NS16550 Serial Ports
2005-04-17 02:20:36 +04: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 05:57:00 +04:00
# include <linux/sched.h>
2005-09-06 05:57:27 +04:00
# include <linux/console.h>
2006-06-07 06:06:20 +04:00
# include <linux/init.h>
2005-04-17 02:20:36 +04:00
# include <asm/processor.h>
2006-01-11 03:54:09 +03:00
# include <asm/udbg.h>
2005-04-17 02:20:36 +04:00
2005-11-23 09:57:25 +03:00
void ( * udbg_putc ) ( char c ) ;
2005-11-30 08:54:12 +03:00
int ( * udbg_getc ) ( void ) ;
2005-09-06 05:56:42 +04:00
int ( * udbg_getc_poll ) ( void ) ;
2006-01-11 03:54:09 +03: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 12:20:16 +04:00
# elif defined(CONFIG_PPC_EARLY_DEBUG_RTAS_PANEL)
2006-01-11 03:54:09 +03:00
/* RTAS panel debug */
2006-06-23 12:20:16 +04:00
udbg_init_rtas_panel ( ) ;
# elif defined(CONFIG_PPC_EARLY_DEBUG_RTAS_CONSOLE)
/* RTAS console debug */
udbg_init_rtas_console ( ) ;
2006-01-11 03:54:09 +03: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 ( ) ;
2007-02-02 10:43:21 +03:00
# elif defined(CONFIG_PPC_EARLY_DEBUG_BEAT)
udbg_init_debug_beat ( ) ;
2007-02-05 01:36:49 +03:00
# elif defined(CONFIG_PPC_EARLY_DEBUG_PAS_REALMODE)
udbg_init_pas_realmode ( ) ;
2007-02-13 07:54:22 +03:00
# elif defined(CONFIG_BOOTX_TEXT)
udbg_init_btext ( ) ;
2007-05-08 06:59:31 +04:00
# elif defined(CONFIG_PPC_EARLY_DEBUG_44x)
/* PPC44x debug */
udbg_init_44x_as1 ( ) ;
2007-07-16 20:43:43 +04:00
# elif defined(CONFIG_PPC_EARLY_DEBUG_CPM)
udbg_init_cpm ( ) ;
2006-01-11 03:54:09 +03:00
# endif
}
2005-09-06 05:57:27 +04:00
/* udbg library, used by xmon et al */
2005-04-17 02:20:36 +04:00
void udbg_puts ( const char * s )
{
2005-09-06 05:56:42 +04:00
if ( udbg_putc ) {
2005-04-17 02:20:36 +04:00
char c ;
if ( s & & * s ! = ' \0 ' ) {
while ( ( c = * s + + ) ! = ' \0 ' )
2005-09-06 05:56:42 +04:00
udbg_putc ( c ) ;
2005-04-17 02:20:36 +04:00
}
}
#if 0
else {
printk ( " %s " , s ) ;
}
# endif
}
int udbg_write ( const char * s , int n )
{
int remain = n ;
char c ;
2005-09-06 05:56:42 +04:00
if ( ! udbg_putc )
2005-04-17 02:20:36 +04:00
return 0 ;
if ( s & & * s ! = ' \0 ' ) {
while ( ( ( c = * s + + ) ! = ' \0 ' ) & & ( remain - - > 0 ) ) {
2005-09-06 05:56:42 +04:00
udbg_putc ( c ) ;
2005-04-17 02:20:36 +04:00
}
}
return n - remain ;
}
int udbg_read ( char * buf , int buflen )
{
2005-11-30 08:54:12 +03:00
char * p = buf ;
int i , c ;
2005-04-17 02:20:36 +04:00
2005-09-06 05:56:42 +04:00
if ( ! udbg_getc )
2005-04-17 02:20:36 +04:00
return 0 ;
for ( i = 0 ; i < buflen ; + + i ) {
do {
2005-09-06 05:56:42 +04:00
c = udbg_getc ( ) ;
2005-11-30 08:54:12 +03:00
if ( c = = - 1 & & i = = 0 )
return - 1 ;
2005-04-17 02:20:36 +04:00
} while ( c = = 0x11 | | c = = 0x13 ) ;
2005-11-30 08:54:12 +03:00
if ( c = = 0 | | c = = - 1 )
2005-04-17 02:20:36 +04:00
break ;
* p + + = c ;
}
return i ;
}
# define UDBG_BUFSIZE 256
void udbg_printf ( const char * fmt , . . . )
{
2005-11-23 09:57:25 +03:00
char buf [ UDBG_BUFSIZE ] ;
2005-04-17 02:20:36 +04:00
va_list args ;
va_start ( args , fmt ) ;
vsnprintf ( buf , UDBG_BUFSIZE , fmt , args ) ;
udbg_puts ( buf ) ;
va_end ( args ) ;
}
2005-12-21 01:37:07 +03:00
void __init udbg_progress ( char * s , unsigned short hex )
{
udbg_puts ( s ) ;
udbg_puts ( " \n " ) ;
}
2005-09-06 05:57:27 +04: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 ,
2007-05-08 11:26:49 +04:00
. flags = CON_PRINTBUFFER | CON_ENABLED | CON_BOOT ,
2005-09-06 05:57:27 +04:00
. index = - 1 ,
} ;
2005-09-07 13:52:38 +04:00
static int early_console_initialized ;
2007-06-10 08:32:43 +04:00
/*
* Called by setup_system after ppc_md - > probe and ppc_md - > early_init .
* Call it again after setting udbg_putc in ppc_md - > setup_arch .
*/
2007-07-26 09:16:05 +04:00
void __init register_early_udbg_console ( void )
2005-09-06 05:57:27 +04:00
{
2005-11-23 09:57:25 +03:00
if ( early_console_initialized )
return ;
2007-05-08 11:26:49 +04:00
2007-06-10 08:32:43 +04:00
if ( ! udbg_putc )
return ;
2007-05-08 11:26:49 +04:00
if ( strstr ( boot_command_line , " udbg-immortal " ) ) {
printk ( KERN_INFO " early console immortal ! \n " ) ;
udbg_console . flags & = ~ CON_BOOT ;
}
2005-09-07 13:52:38 +04:00
early_console_initialized = 1 ;
2005-09-06 05:57:27 +04:00
register_console ( & udbg_console ) ;
}
#if 0 /* if you want to use this as a regular output console */
console_initcall ( register_udbg_console ) ;
# endif