]>
Commit | Line | Data |
---|---|---|
1543610a PA |
1 | /* -*- linux-c -*- ------------------------------------------------------- * |
2 | * | |
3 | * Copyright (C) 1991, 1992 Linus Torvalds | |
4 | * Copyright 2007 rPath, Inc. - All Rights Reserved | |
df7699c5 | 5 | * Copyright 2009 Intel Corporation; author H. Peter Anvin |
1543610a PA |
6 | * |
7 | * This file is part of the Linux kernel, and is made available under | |
8 | * the terms of the GNU General Public License version 2. | |
9 | * | |
10 | * ----------------------------------------------------------------------- */ | |
11 | ||
12 | /* | |
fa97bdf9 | 13 | * Very simple screen and serial I/O |
1543610a PA |
14 | */ |
15 | ||
16 | #include "boot.h" | |
17 | ||
f4ed2877 | 18 | int early_serial_base; |
fa97bdf9 PE |
19 | |
20 | #define XMTRDY 0x20 | |
21 | ||
fa97bdf9 | 22 | #define TXR 0 /* Transmit register (WRITE) */ |
fa97bdf9 | 23 | #define LSR 5 /* Line Status */ |
fa97bdf9 | 24 | |
1543610a PA |
25 | /* |
26 | * These functions are in .inittext so they can be used to signal | |
27 | * error during initialization. | |
28 | */ | |
29 | ||
fa97bdf9 | 30 | static void __attribute__((section(".inittext"))) serial_putchar(int ch) |
1543610a | 31 | { |
fa97bdf9 | 32 | unsigned timeout = 0xffff; |
1543610a | 33 | |
fa97bdf9 PE |
34 | while ((inb(early_serial_base + LSR) & XMTRDY) == 0 && --timeout) |
35 | cpu_relax(); | |
36 | ||
37 | outb(ch, early_serial_base + TXR); | |
38 | } | |
39 | ||
40 | static void __attribute__((section(".inittext"))) bios_putchar(int ch) | |
41 | { | |
42 | struct biosregs ireg; | |
1543610a | 43 | |
df7699c5 PA |
44 | initregs(&ireg); |
45 | ireg.bx = 0x0007; | |
46 | ireg.cx = 0x0001; | |
47 | ireg.ah = 0x0e; | |
48 | ireg.al = ch; | |
49 | intcall(0x10, &ireg, NULL); | |
1543610a PA |
50 | } |
51 | ||
fa97bdf9 PE |
52 | void __attribute__((section(".inittext"))) putchar(int ch) |
53 | { | |
54 | if (ch == '\n') | |
55 | putchar('\r'); /* \n -> \r\n */ | |
56 | ||
57 | bios_putchar(ch); | |
58 | ||
59 | if (early_serial_base != 0) | |
60 | serial_putchar(ch); | |
61 | } | |
62 | ||
1543610a PA |
63 | void __attribute__((section(".inittext"))) puts(const char *str) |
64 | { | |
df7699c5 | 65 | while (*str) |
1543610a | 66 | putchar(*str++); |
1543610a PA |
67 | } |
68 | ||
69 | /* | |
70 | * Read the CMOS clock through the BIOS, and return the | |
71 | * seconds in BCD. | |
72 | */ | |
73 | ||
74 | static u8 gettime(void) | |
75 | { | |
df7699c5 | 76 | struct biosregs ireg, oreg; |
1543610a | 77 | |
df7699c5 PA |
78 | initregs(&ireg); |
79 | ireg.ah = 0x02; | |
80 | intcall(0x1a, &ireg, &oreg); | |
1543610a | 81 | |
df7699c5 | 82 | return oreg.dh; |
1543610a PA |
83 | } |
84 | ||
85 | /* | |
86 | * Read from the keyboard | |
87 | */ | |
88 | int getchar(void) | |
89 | { | |
df7699c5 PA |
90 | struct biosregs ireg, oreg; |
91 | ||
92 | initregs(&ireg); | |
93 | /* ireg.ah = 0x00; */ | |
94 | intcall(0x16, &ireg, &oreg); | |
1543610a | 95 | |
df7699c5 | 96 | return oreg.al; |
1543610a PA |
97 | } |
98 | ||
99 | static int kbd_pending(void) | |
100 | { | |
df7699c5 PA |
101 | struct biosregs ireg, oreg; |
102 | ||
103 | initregs(&ireg); | |
104 | ireg.ah = 0x01; | |
105 | intcall(0x16, &ireg, &oreg); | |
106 | ||
107 | return !(oreg.eflags & X86_EFLAGS_ZF); | |
1543610a PA |
108 | } |
109 | ||
110 | void kbd_flush(void) | |
111 | { | |
112 | for (;;) { | |
113 | if (!kbd_pending()) | |
114 | break; | |
115 | getchar(); | |
116 | } | |
117 | } | |
118 | ||
119 | int getchar_timeout(void) | |
120 | { | |
121 | int cnt = 30; | |
122 | int t0, t1; | |
123 | ||
124 | t0 = gettime(); | |
125 | ||
126 | while (cnt) { | |
127 | if (kbd_pending()) | |
128 | return getchar(); | |
129 | ||
130 | t1 = gettime(); | |
131 | if (t0 != t1) { | |
132 | cnt--; | |
133 | t0 = t1; | |
134 | } | |
135 | } | |
136 | ||
137 | return 0; /* Timeout! */ | |
138 | } | |
fa97bdf9 | 139 |