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! */
 | 
						|
}
 | 
						|
 |