Commit | Line | Data |
---|---|---|
1543610a PA |
1 | /* -*- linux-c -*- ------------------------------------------------------- * |
2 | * | |
3 | * Copyright (C) 1991, 1992 Linus Torvalds | |
4 | * Copyright 2007 rPath, Inc. - All Rights Reserved | |
5 | * | |
6 | * This file is part of the Linux kernel, and is made available under | |
7 | * the terms of the GNU General Public License version 2. | |
8 | * | |
9 | * ----------------------------------------------------------------------- */ | |
10 | ||
11 | /* | |
12 | * arch/i386/boot/tty.c | |
13 | * | |
14 | * Very simple screen I/O | |
15 | * XXX: Probably should add very simple serial I/O? | |
16 | */ | |
17 | ||
18 | #include "boot.h" | |
19 | ||
20 | /* | |
21 | * These functions are in .inittext so they can be used to signal | |
22 | * error during initialization. | |
23 | */ | |
24 | ||
25 | void __attribute__((section(".inittext"))) putchar(int ch) | |
26 | { | |
27 | unsigned char c = ch; | |
28 | ||
29 | if (c == '\n') | |
30 | putchar('\r'); /* \n -> \r\n */ | |
31 | ||
32 | /* int $0x10 is known to have bugs involving touching registers | |
33 | it shouldn't. Be extra conservative... */ | |
34 | asm volatile("pushal; int $0x10; popal" | |
35 | : : "b" (0x0007), "c" (0x0001), "a" (0x0e00|ch)); | |
36 | } | |
37 | ||
38 | void __attribute__((section(".inittext"))) puts(const char *str) | |
39 | { | |
40 | int n = 0; | |
41 | while (*str) { | |
42 | putchar(*str++); | |
43 | n++; | |
44 | } | |
45 | } | |
46 | ||
47 | /* | |
48 | * Read the CMOS clock through the BIOS, and return the | |
49 | * seconds in BCD. | |
50 | */ | |
51 | ||
52 | static u8 gettime(void) | |
53 | { | |
54 | u16 ax = 0x0200; | |
55 | u16 cx, dx; | |
56 | ||
57 | asm("int $0x1a" | |
58 | : "+a" (ax), "=c" (cx), "=d" (dx) | |
59 | : : "ebx", "esi", "edi"); | |
60 | ||
61 | return dx >> 8; | |
62 | } | |
63 | ||
64 | /* | |
65 | * Read from the keyboard | |
66 | */ | |
67 | int getchar(void) | |
68 | { | |
69 | u16 ax = 0; | |
70 | asm("int $0x16" : "+a" (ax)); | |
71 | ||
72 | return ax & 0xff; | |
73 | } | |
74 | ||
75 | static int kbd_pending(void) | |
76 | { | |
77 | u8 pending; | |
78 | asm("int $0x16; setnz %0" | |
79 | : "=rm" (pending) | |
80 | : "a" (0x0100)); | |
81 | return pending; | |
82 | } | |
83 | ||
84 | void kbd_flush(void) | |
85 | { | |
86 | for (;;) { | |
87 | if (!kbd_pending()) | |
88 | break; | |
89 | getchar(); | |
90 | } | |
91 | } | |
92 | ||
93 | int getchar_timeout(void) | |
94 | { | |
95 | int cnt = 30; | |
96 | int t0, t1; | |
97 | ||
98 | t0 = gettime(); | |
99 | ||
100 | while (cnt) { | |
101 | if (kbd_pending()) | |
102 | return getchar(); | |
103 | ||
104 | t1 = gettime(); | |
105 | if (t0 != t1) { | |
106 | cnt--; | |
107 | t0 = t1; | |
108 | } | |
109 | } | |
110 | ||
111 | return 0; /* Timeout! */ | |
112 | } |