diff options
Diffstat (limited to 'arch/x86/boot/tty.c')
| -rw-r--r-- | arch/x86/boot/tty.c | 112 | 
1 files changed, 112 insertions, 0 deletions
diff --git a/arch/x86/boot/tty.c b/arch/x86/boot/tty.c new file mode 100644 index 00000000000..f3f14bd2637 --- /dev/null +++ b/arch/x86/boot/tty.c @@ -0,0 +1,112 @@ +/* -*- linux-c -*- ------------------------------------------------------- * + * + *   Copyright (C) 1991, 1992 Linus Torvalds + *   Copyright 2007 rPath, Inc. - All Rights Reserved + * + *   This file is part of the Linux kernel, and is made available under + *   the terms of the GNU General Public License version 2. + * + * ----------------------------------------------------------------------- */ + +/* + * arch/i386/boot/tty.c + * + * Very simple screen I/O + * XXX: Probably should add very simple serial I/O? + */ + +#include "boot.h" + +/* + * These functions are in .inittext so they can be used to signal + * error during initialization. + */ + +void __attribute__((section(".inittext"))) putchar(int ch) +{ +	unsigned char c = ch; + +	if (c == '\n') +		putchar('\r');	/* \n -> \r\n */ + +	/* int $0x10 is known to have bugs involving touching registers +	   it shouldn't.  Be extra conservative... */ +	asm volatile("pushal; pushw %%ds; int $0x10; popw %%ds; popal" +		     : : "b" (0x0007), "c" (0x0001), "a" (0x0e00|ch)); +} + +void __attribute__((section(".inittext"))) puts(const char *str) +{ +	int n = 0; +	while (*str) { +		putchar(*str++); +		n++; +	} +} + +/* + * Read the CMOS clock through the BIOS, and return the + * seconds in BCD. + */ + +static u8 gettime(void) +{ +	u16 ax = 0x0200; +	u16 cx, dx; + +	asm volatile("int $0x1a" +		     : "+a" (ax), "=c" (cx), "=d" (dx) +		     : : "ebx", "esi", "edi"); + +	return dx >> 8; +} + +/* + * Read from the keyboard + */ +int getchar(void) +{ +	u16 ax = 0; +	asm volatile("int $0x16" : "+a" (ax)); + +	return ax & 0xff; +} + +static int kbd_pending(void) +{ +	u8 pending; +	asm volatile("int $0x16; setnz %0" +		     : "=rm" (pending) +		     : "a" (0x0100)); +	return pending; +} + +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! */ +}  |