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 ) ;
2009-03-09 07:52:41 +00:00
void ( * udbg_flush ) ( void ) ;
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 ( ) ;
2007-02-02 16:43:21 +09:00
# elif defined(CONFIG_PPC_EARLY_DEBUG_BEAT)
udbg_init_debug_beat ( ) ;
2007-02-04 16:36:49 -06:00
# elif defined(CONFIG_PPC_EARLY_DEBUG_PAS_REALMODE)
udbg_init_pas_realmode ( ) ;
2007-02-13 15:54:22 +11:00
# elif defined(CONFIG_BOOTX_TEXT)
udbg_init_btext ( ) ;
2007-05-08 12:59:31 +10:00
# elif defined(CONFIG_PPC_EARLY_DEBUG_44x)
/* PPC44x debug */
udbg_init_44x_as1 ( ) ;
2007-12-21 15:39:26 +11:00
# elif defined(CONFIG_PPC_EARLY_DEBUG_40x)
/* PPC40x debug */
udbg_init_40x_realmode ( ) ;
2007-07-16 11:43:43 -05:00
# elif defined(CONFIG_PPC_EARLY_DEBUG_CPM)
udbg_init_cpm ( ) ;
2009-12-12 06:31:51 +00:00
# elif defined(CONFIG_PPC_EARLY_DEBUG_USBGECKO)
udbg_init_usbgecko ( ) ;
2011-04-14 22:32:08 +00:00
# elif defined(CONFIG_PPC_EARLY_DEBUG_WSP)
udbg_init_wsp ( ) ;
2006-01-11 11:54:09 +11:00
# endif
2007-12-11 14:48:24 +11:00
# ifdef CONFIG_PPC_EARLY_DEBUG
console_loglevel = 10 ;
# endif
2006-01-11 11:54:09 +11:00
}
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
}
2009-03-09 07:52:41 +00:00
if ( udbg_flush )
udbg_flush ( ) ;
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
}
}
2009-03-09 07:52:41 +00:00
if ( udbg_flush )
udbg_flush ( ) ;
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 ,
2008-04-24 15:13:14 +10:00
. flags = CON_PRINTBUFFER | CON_ENABLED | CON_BOOT | CON_ANYTIME ,
2008-04-24 15:13:13 +10:00
. index = 0 ,
2005-09-06 11:57:27 +10:00
} ;
2005-09-07 19:52:38 +10:00
static int early_console_initialized ;
2007-06-10 14:32:43 +10: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 00:16:05 -05:00
void __init register_early_udbg_console ( void )
2005-09-06 11:57:27 +10:00
{
2005-11-23 17:57:25 +11:00
if ( early_console_initialized )
return ;
2007-05-08 00:26:49 -07:00
2007-06-10 14:32:43 +10:00
if ( ! udbg_putc )
return ;
2007-05-08 00:26:49 -07:00
if ( strstr ( boot_command_line , " udbg-immortal " ) ) {
printk ( KERN_INFO " early console immortal ! \n " ) ;
udbg_console . flags & = ~ CON_BOOT ;
}
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