Merge branch 'sas-fixes' of master.kernel.org:/pub/scm/linux/kernel/git/jgarzik/misc-2.6
[linux-2.6] / arch / i386 / boot / tty.c
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; pushw %%ds; int $0x10; popw %%ds; 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 volatile("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 volatile("int $0x16" : "+a" (ax));
71
72         return ax & 0xff;
73 }
74
75 static int kbd_pending(void)
76 {
77         u8 pending;
78         asm volatile("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 }