blob: def2451f46aefe70fe38d5ed3554a380f710a6e2 [file] [log] [blame]
H. Peter Anvin15436102007-07-11 12:18:45 -07001/* -*- linux-c -*- ------------------------------------------------------- *
2 *
3 * Copyright (C) 1991, 1992 Linus Torvalds
4 * Copyright 2007 rPath, Inc. - All Rights Reserved
H. Peter Anvindf7699c2009-04-01 18:13:46 -07005 * Copyright 2009 Intel Corporation; author H. Peter Anvin
H. Peter Anvin15436102007-07-11 12:18:45 -07006 *
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/*
Pekka Enbergfa97bdf2010-07-11 11:06:57 +030013 * Very simple screen and serial I/O
H. Peter Anvin15436102007-07-11 12:18:45 -070014 */
15
16#include "boot.h"
17
Yinghai Luf4ed2872010-08-02 02:17:31 -070018int early_serial_base;
Pekka Enbergfa97bdf2010-07-11 11:06:57 +030019
20#define XMTRDY 0x20
21
Pekka Enbergfa97bdf2010-07-11 11:06:57 +030022#define TXR 0 /* Transmit register (WRITE) */
Pekka Enbergfa97bdf2010-07-11 11:06:57 +030023#define LSR 5 /* Line Status */
Pekka Enbergfa97bdf2010-07-11 11:06:57 +030024
H. Peter Anvin15436102007-07-11 12:18:45 -070025/*
26 * These functions are in .inittext so they can be used to signal
27 * error during initialization.
28 */
29
Pekka Enbergfa97bdf2010-07-11 11:06:57 +030030static void __attribute__((section(".inittext"))) serial_putchar(int ch)
31{
32 unsigned timeout = 0xffff;
33
34 while ((inb(early_serial_base + LSR) & XMTRDY) == 0 && --timeout)
35 cpu_relax();
36
37 outb(ch, early_serial_base + TXR);
38}
39
40static void __attribute__((section(".inittext"))) bios_putchar(int ch)
H. Peter Anvin15436102007-07-11 12:18:45 -070041{
H. Peter Anvindf7699c2009-04-01 18:13:46 -070042 struct biosregs ireg;
H. Peter Anvin15436102007-07-11 12:18:45 -070043
H. Peter Anvindf7699c2009-04-01 18:13:46 -070044 initregs(&ireg);
45 ireg.bx = 0x0007;
46 ireg.cx = 0x0001;
47 ireg.ah = 0x0e;
48 ireg.al = ch;
49 intcall(0x10, &ireg, NULL);
H. Peter Anvin15436102007-07-11 12:18:45 -070050}
51
Pekka Enbergfa97bdf2010-07-11 11:06:57 +030052void __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
H. Peter Anvin15436102007-07-11 12:18:45 -070063void __attribute__((section(".inittext"))) puts(const char *str)
64{
H. Peter Anvindf7699c2009-04-01 18:13:46 -070065 while (*str)
H. Peter Anvin15436102007-07-11 12:18:45 -070066 putchar(*str++);
H. Peter Anvin15436102007-07-11 12:18:45 -070067}
68
69/*
70 * Read the CMOS clock through the BIOS, and return the
71 * seconds in BCD.
72 */
73
74static u8 gettime(void)
75{
H. Peter Anvindf7699c2009-04-01 18:13:46 -070076 struct biosregs ireg, oreg;
H. Peter Anvin15436102007-07-11 12:18:45 -070077
H. Peter Anvindf7699c2009-04-01 18:13:46 -070078 initregs(&ireg);
79 ireg.ah = 0x02;
80 intcall(0x1a, &ireg, &oreg);
H. Peter Anvin15436102007-07-11 12:18:45 -070081
H. Peter Anvindf7699c2009-04-01 18:13:46 -070082 return oreg.dh;
H. Peter Anvin15436102007-07-11 12:18:45 -070083}
84
85/*
86 * Read from the keyboard
87 */
88int getchar(void)
89{
H. Peter Anvindf7699c2009-04-01 18:13:46 -070090 struct biosregs ireg, oreg;
H. Peter Anvin15436102007-07-11 12:18:45 -070091
H. Peter Anvindf7699c2009-04-01 18:13:46 -070092 initregs(&ireg);
93 /* ireg.ah = 0x00; */
94 intcall(0x16, &ireg, &oreg);
95
96 return oreg.al;
H. Peter Anvin15436102007-07-11 12:18:45 -070097}
98
99static int kbd_pending(void)
100{
H. Peter Anvindf7699c2009-04-01 18:13:46 -0700101 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);
H. Peter Anvin15436102007-07-11 12:18:45 -0700108}
109
110void kbd_flush(void)
111{
112 for (;;) {
113 if (!kbd_pending())
114 break;
115 getchar();
116 }
117}
118
119int 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}
Pekka Enbergfa97bdf2010-07-11 11:06:57 +0300139