2019-06-04 11:11:30 +03:00
// SPDX-License-Identifier: GPL-2.0-only
2007-07-11 23:18:45 +04:00
/* -*- linux-c -*- ------------------------------------------------------- *
*
* Copyright ( C ) 1991 , 1992 Linus Torvalds
* Copyright 2007 rPath , Inc . - All Rights Reserved
2009-04-02 05:13:46 +04:00
* Copyright 2009 Intel Corporation ; author H . Peter Anvin
2007-07-11 23:18:45 +04:00
*
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
/*
2010-07-11 12:06:57 +04:00
* Very simple screen and serial I / O
2007-07-11 23:18:45 +04:00
*/
# include "boot.h"
2010-08-02 13:17:31 +04:00
int early_serial_base ;
2010-07-11 12:06:57 +04:00
# define XMTRDY 0x20
# define TXR 0 /* Transmit register (WRITE) */
# define LSR 5 /* Line Status */
2007-07-11 23:18:45 +04:00
/*
* These functions are in . inittext so they can be used to signal
* error during initialization .
*/
2010-07-11 12:06:57 +04:00
static void __attribute__ ( ( section ( " .inittext " ) ) ) serial_putchar ( int ch )
2007-07-11 23:18:45 +04:00
{
2010-07-11 12:06:57 +04:00
unsigned timeout = 0xffff ;
2007-07-11 23:18:45 +04:00
2010-07-11 12:06:57 +04:00
while ( ( inb ( early_serial_base + LSR ) & XMTRDY ) = = 0 & & - - timeout )
cpu_relax ( ) ;
outb ( ch , early_serial_base + TXR ) ;
}
static void __attribute__ ( ( section ( " .inittext " ) ) ) bios_putchar ( int ch )
{
struct biosregs ireg ;
2007-07-11 23:18:45 +04:00
2009-04-02 05:13:46 +04:00
initregs ( & ireg ) ;
ireg . bx = 0x0007 ;
ireg . cx = 0x0001 ;
ireg . ah = 0x0e ;
ireg . al = ch ;
intcall ( 0x10 , & ireg , NULL ) ;
2007-07-11 23:18:45 +04:00
}
2010-07-11 12:06:57 +04:00
void __attribute__ ( ( section ( " .inittext " ) ) ) putchar ( int ch )
{
if ( ch = = ' \n ' )
putchar ( ' \r ' ) ; /* \n -> \r\n */
bios_putchar ( ch ) ;
if ( early_serial_base ! = 0 )
serial_putchar ( ch ) ;
}
2007-07-11 23:18:45 +04:00
void __attribute__ ( ( section ( " .inittext " ) ) ) puts ( const char * str )
{
2009-04-02 05:13:46 +04:00
while ( * str )
2007-07-11 23:18:45 +04:00
putchar ( * str + + ) ;
}
/*
* Read the CMOS clock through the BIOS , and return the
* seconds in BCD .
*/
static u8 gettime ( void )
{
2009-04-02 05:13:46 +04:00
struct biosregs ireg , oreg ;
2007-07-11 23:18:45 +04:00
2009-04-02 05:13:46 +04:00
initregs ( & ireg ) ;
ireg . ah = 0x02 ;
intcall ( 0x1a , & ireg , & oreg ) ;
2007-07-11 23:18:45 +04:00
2009-04-02 05:13:46 +04:00
return oreg . dh ;
2007-07-11 23:18:45 +04:00
}
/*
* Read from the keyboard
*/
int getchar ( void )
{
2009-04-02 05:13:46 +04:00
struct biosregs ireg , oreg ;
initregs ( & ireg ) ;
/* ireg.ah = 0x00; */
intcall ( 0x16 , & ireg , & oreg ) ;
2007-07-11 23:18:45 +04:00
2009-04-02 05:13:46 +04:00
return oreg . al ;
2007-07-11 23:18:45 +04:00
}
static int kbd_pending ( void )
{
2009-04-02 05:13:46 +04:00
struct biosregs ireg , oreg ;
initregs ( & ireg ) ;
ireg . ah = 0x01 ;
intcall ( 0x16 , & ireg , & oreg ) ;
return ! ( oreg . eflags & X86_EFLAGS_ZF ) ;
2007-07-11 23:18:45 +04:00
}
void kbd_flush ( void )
{
for ( ; ; ) {
if ( ! kbd_pending ( ) )
break ;
getchar ( ) ;
}
}
int getchar_timeout ( void )
{
int cnt = 30 ;
int t0 , t1 ;
t0 = gettime ( ) ;
while ( cnt ) {
if ( kbd_pending ( ) )
return getchar ( ) ;
t1 = gettime ( ) ;
if ( t0 ! = t1 ) {
cnt - - ;
t0 = t1 ;
}
}
return 0 ; /* Timeout! */
}
2010-07-11 12:06:57 +04:00