 f4ed2877b1
			
		
	
	
	f4ed2877b1
	
	
	
		
			
			Separate early_serial_console from tty.c
This allows for reuse of
early_serial_console.c/string.c/printf.c/cmdline.c in boot/compressed/.
-v2: according to hpa, don't include string.c etc
-v3: compressed/misc.c must have early_serial_base as static, so move it back to tty.c
     for setup code
Signed-off-by: Yinghai Lu <yinghai@kernel.org>
LKML-Reference: <4C568D2B.205@kernel.org>
Signed-off-by: H. Peter Anvin <hpa@linux.intel.com>
		
	
			
		
			
				
	
	
		
			139 lines
		
	
	
	
		
			2.4 KiB
			
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			139 lines
		
	
	
	
		
			2.4 KiB
			
		
	
	
	
		
			C
		
	
	
	
	
	
| /* -*- linux-c -*- ------------------------------------------------------- *
 | |
|  *
 | |
|  *   Copyright (C) 1991, 1992 Linus Torvalds
 | |
|  *   Copyright 2007 rPath, Inc. - All Rights Reserved
 | |
|  *   Copyright 2009 Intel Corporation; author H. Peter Anvin
 | |
|  *
 | |
|  *   This file is part of the Linux kernel, and is made available under
 | |
|  *   the terms of the GNU General Public License version 2.
 | |
|  *
 | |
|  * ----------------------------------------------------------------------- */
 | |
| 
 | |
| /*
 | |
|  * Very simple screen and serial I/O
 | |
|  */
 | |
| 
 | |
| #include "boot.h"
 | |
| 
 | |
| int early_serial_base;
 | |
| 
 | |
| #define XMTRDY          0x20
 | |
| 
 | |
| #define TXR             0       /*  Transmit register (WRITE) */
 | |
| #define LSR             5       /*  Line Status               */
 | |
| 
 | |
| /*
 | |
|  * These functions are in .inittext so they can be used to signal
 | |
|  * error during initialization.
 | |
|  */
 | |
| 
 | |
| static void __attribute__((section(".inittext"))) serial_putchar(int ch)
 | |
| {
 | |
| 	unsigned timeout = 0xffff;
 | |
| 
 | |
| 	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;
 | |
| 
 | |
| 	initregs(&ireg);
 | |
| 	ireg.bx = 0x0007;
 | |
| 	ireg.cx = 0x0001;
 | |
| 	ireg.ah = 0x0e;
 | |
| 	ireg.al = ch;
 | |
| 	intcall(0x10, &ireg, NULL);
 | |
| }
 | |
| 
 | |
| 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);
 | |
| }
 | |
| 
 | |
| void __attribute__((section(".inittext"))) puts(const char *str)
 | |
| {
 | |
| 	while (*str)
 | |
| 		putchar(*str++);
 | |
| }
 | |
| 
 | |
| /*
 | |
|  * Read the CMOS clock through the BIOS, and return the
 | |
|  * seconds in BCD.
 | |
|  */
 | |
| 
 | |
| static u8 gettime(void)
 | |
| {
 | |
| 	struct biosregs ireg, oreg;
 | |
| 
 | |
| 	initregs(&ireg);
 | |
| 	ireg.ah = 0x02;
 | |
| 	intcall(0x1a, &ireg, &oreg);
 | |
| 
 | |
| 	return oreg.dh;
 | |
| }
 | |
| 
 | |
| /*
 | |
|  * Read from the keyboard
 | |
|  */
 | |
| int getchar(void)
 | |
| {
 | |
| 	struct biosregs ireg, oreg;
 | |
| 
 | |
| 	initregs(&ireg);
 | |
| 	/* ireg.ah = 0x00; */
 | |
| 	intcall(0x16, &ireg, &oreg);
 | |
| 
 | |
| 	return oreg.al;
 | |
| }
 | |
| 
 | |
| static int kbd_pending(void)
 | |
| {
 | |
| 	struct biosregs ireg, oreg;
 | |
| 
 | |
| 	initregs(&ireg);
 | |
| 	ireg.ah = 0x01;
 | |
| 	intcall(0x16, &ireg, &oreg);
 | |
| 
 | |
| 	return !(oreg.eflags & X86_EFLAGS_ZF);
 | |
| }
 | |
| 
 | |
| 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! */
 | |
| }
 | |
| 
 |